I want to put a command into a shell script which will create a symlink to directory, but this script could be run over and over, so on subsequent invocations, the command should not change anything.
Here is the directory structure:
% tree /tmp/test_symlink
/tmp/test_symlink
├── foo
└── repo
└── resources
└── snippets
├── php.snippets
├── sh.snippets
├── snippets.snippets
├── sql.snippets
└── vim.snippets
I want to create a symlink in foo/
called snippets which points to
the directory /tmp/test_symlink/repo/resources/snippets
.
So I run:
% ln -sfv /tmp/test_symlink/repo/resources/snippets /tmp/test_symlink/foo/snippets
'/tmp/test_symlink/foo/snippets' -> '/tmp/test_symlink/repo/resources/snippets'
which gives the desired result.
% tree /tmp/test_symlink
/tmp/test_symlink
├── foo
│ └── snippets -> /tmp/test_symlink/repo/resources/snippets
└── repo
└── resources
└── snippets
├── php.snippets
├── sh.snippets
├── snippets.snippets
├── sql.snippets
└── vim.snippets
5 directories, 5 files
However, when the command is run again,
% ln -sfv /tmp/test_symlink/repo/resources/snippets /tmp/test_symlink/foo/snippets
'/tmp/test_symlink/foo/snippets/snippets' -> '/tmp/test_symlink/repo/resources/snippets'
it creates a symlink to a directory, where the symlink aleady exists puts symlink inside the real directory
% tree /tmp/test_symlink
/tmp/test_symlink
├── foo
│ └── snippets -> /tmp/test_symlink/repo/resources/snippets
└── repo
└── resources
└── snippets
├── php.snippets
├── sh.snippets
├── snippets -> /tmp/test_symlink/repo/resources/snippets
├── snippets.snippets
├── sql.snippets
└── vim.snippets
why is this happening and how can I modify the command so that subsequent invocations won't create this weird effect?
Best Answer
You should use the
-T
option for this, it tellsln
to always treat the link name as the desired link name, never as a directory.Without this option, if you give
ln
a link name which exists as a directory, it creates a new link to the target inside that directory.Note that
-T
is a GNU-ism (at least, it’s not in POSIX), but you’re already using-v
which is a GNU-ism too so I imagine that’s not an issue.Alternatively, you can just specify the parent directory as the link name, and the link will always be (re-)created there:
This works because your symlink has the same name as the target.