macOS Cannot Create Valid Symlink From Terminal Using Relative Paths
Using the following snippet it creates an invalid symlink. But according to other answers it should work fine.
# make a temp dir and save path to var.
# set dir (mktemp -d) # fish shell only!
dir=$(mktemp -d) # bash/zsh
cd $dir
mkdir a b
echo 'text file' > a/file.txt
ln -s a/file.txt b/
open .
When you see the symlink in Finder it doesn't recognise the file type in Quick Preview and when you open it Finder complains 'the original item cannot be found'.
If you use absolute paths everything works fine. See below:
rm b/file.txt
ln -s $dir/a/file.txt $dir/b/
open .
Then you can see symlink is correctly make and you can even read the file content in Quick Preview.
How is this happening? I've checked that ln is /bin/ln
. I'm on macOS Catalina 10.15.7 (19H2).
Note that this is about the filesystem and does not matter which shell you are using.
The issue is that the symbolic link just contains the text you passed to it and then the OS tries to resolve it from the actual path of the link. The link works as if you cd to where you store the link
So what happens is when you want to see b/file.txt the OS tries to open the file a/file.txt relative to directory b (ie $dir/b/a/file.txt) What you want the link to contain is ../a/file.txt
To create it from $dir
ln -s ../a/file.txt b/
Or from anywhere
ln -s ../a/file.txt $dir/b/
This is not related to fish
nor macOS in general, the resulting symlink is just broken
$ mkdir a b
$ touch a/foo.txt
$ ln -s a/foo.txt b/
$ cd b
$ cat foo.txt
cat: foo.txt: No such file or directory
$ ll foo.txt
lrwxr-xr-x 1 pse staff 9 Feb 1 13:14 foo.txt@ -> a/foo.txt
Basically you need to think ahead when creating symlinks in a directory which is different from the current one. I find it easier to run
$ cd b
$ ln -s ../a/foo.txt .
or just avoid relative symlinks in general.