4

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).

correct symlink and quick preview

2
  • First note - apart fromn the first line set this is true for all shells - and please make it clear that it is fish I wasted time as the question is long enough the tags can't be seen
    – mmmmmm
    Commented Feb 1, 2021 at 11:46
  • @mmmmmm Sorry. Thought the tag was enough and I wanted to give a complete snippet you could copy paste. Ironically that was to save time of people willing to answer. 🙄
    – user14492
    Commented Feb 1, 2021 at 15:03

2 Answers 2

5

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/
2
  • Agh h@mmmmmm 🤔. Thanks for the explanation. So if I do ln ./a/file.txt ./b/ to make a hard link it works. Sorry about the set confusion. Join the friendly side!
    – user14492
    Commented Feb 1, 2021 at 15:13
  • Yes but I think fpor different reasons - I think your original commands work if you use hard links - there are no strings in hard links just sharing of inodes (Oh I just left the friendly shell as I had to write a 5 line function in it so yet another language - maybe better than sh but... Now on xonsh so scripting is python)
    – mmmmmm
    Commented Feb 1, 2021 at 16:23
8

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.

2
  • So you cannot create symlink to folders you're not in? Is this true on all OSes?
    – user14492
    Commented Feb 1, 2021 at 15:07
  • 4
    @user14492 You can, you just need to keep in mind that the link needs to relative to the directory it is created in, not to the directory you are in when running ln -s.
    – nohillside
    Commented Feb 1, 2021 at 15:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .