Too many levels of symbolic links
I created this file structure:
When I run this command:
ln -s test/src test/firefox
I would expect a symbolic link
test/firefox/src to be created pointing to
test/src, however I get this error instead:
-bash: cd: src: Too many levels of symbolic links
- What am I doing wrong?
- Can you not create a symbolic link to one folder which is stored in a
sibling of that folder?
- What’s the point of this?
On the surface, what you’ve suggested you’ve tried works for me.
$ mkdir -p test/src test/firefox $ tree --noreport -fp . `-- [drwxrwxr-x] ./test |-- [drwxrwxr-x] ./test/firefox `-- [drwxrwxr-x] ./test/src
Make the symbolic link:
$ ln -s test/src test/firefox $ tree --noreport -fp . `-- [drwxrwxr-x] ./test |-- [drwxrwxr-x] ./test/firefox | `-- [lrwxrwxrwx] ./test/firefox/src -> test/src `-- [drwxrwxr-x] ./test/src
Running it a 2nd time would typically produce this:
$ ln -s test/src test/firefox ln: failed to create symbolic link ‘test/firefox/src’: File exists
So you likely have something else going on here. I would suspect that you have a circular reference where a link is pointing back onto itself.
You can use
find to sleuth this out a bit:
$ cd /suspected/directory $ find -L ./ -mindepth 15
As Dubu points out in a comment, the issue lies in your relative paths. I had a similar problem symlinking my nginx configuration from
/etc/nginx. If you create your symlink like this:
cd /usr/local/etc ln -s nginx/ /etc/nginx
You will in fact make the link /etc/nginx -> /etc/nginx, because the source path is relative to the link’s path. The solution is as simple as using absolute paths:
ln -s /usr/local/etc/nginx /etc/nginx
If you want to use relative paths and have them behave the way you probably expect them to, you can use the
$PWD variable to easily add in the path to the current working directory path, like so:
cd /usr/local/etc ln -s "$PWD/nginx/" /etc/nginx
Make sure that the path is in double quotes, to make sure things like spaces in your current path are escaped. Note that you must use double quotes when doing this, as
$PWD will not be substituted if you use single quotes.
Symlinks are relative to the parent directory of the link, not of the current directory of the
When you do:
cd /top/dir ln -s test/src test/firefox
test/firefox is a directory), you’re making a
test/firefox/src symlink whose target is
test/src is relative to the
test/firefox directory, so that’s a symlink to
If you wanted that symlink to be a link to
/top/dir/test/src, you’d need to write:
ln -s ../src test/firefox/
ln -s /top/dir/test/src test/firefox/
though it’s generally a bad idea to make symlinks to absolute paths as they are easily broken when directories are renamed or filesystems are mounted elsewhere.
ln, you can use its
-r option to let it make the calculation by itself:
$ ln -rs test/src test/firefox/ $ ls -ld test/firefox/src lrwxrwxrwx 1 chazelas chazelas 6 Nov 29 15:59 test/firefox/src -> ../src
Use the absolute path instead of the relative path, then it will work.
ln -s /home/user/test/src /home/user/test/firefox
The answer is to use absolute path. But it can be annoying to type the full path for something that is in the current directory. You can use command substitution of pwd to avoid that.
If your target is in the current directory:
ln -s "$(pwd)"/target abs/path/to/link
If your link should be in the current directory:
ln -s /abs/path/to/target "$(pwd)"
I’ve been battling with this for a while and absolute paths are not an option because I need to dockerize my pipeline where relative paths are critical. I finally figured it out:
SRC=$(realpath --relative-to "$DST" -- "$SRC")