I'm trying to better understand symbolic links... and not having very much luck. This is my actual shell output with username/host changed:
username@host:~$ mkdir actual
username@host:~$ mkdir proper
username@host:~$ touch actual/file-1.txt
username@host:~$ echo "file 1" > actual/file-1.txt
username@host:~$ touch actual/file-2.txt
username@host:~$ echo "file 2" > actual/file-2.txt
username@host:~$ ln -s actual/file-1.txt actual/file-2.txt proper
username@host:~$ # Now, try to use the files through their links
username@host:~$ cat proper/file-1.txt
cat: proper/file-1.txt: No such file or directory
username@host:~$ cat proper/file-2.txt
cat: proper/file-2.txt: No such file or directory
username@host:~$ # Check that actual files do in fact exist
username@host:~$ cat actual/file-1.txt
file 1
username@host:~$ cat actual/file-2.txt
file 2
username@host:~$ # Remove the links and go home :(
username@host:~$ rm proper/file-1.txt
username@host:~$ rm proper/file-2.txtI thought that a symbolic link was supposed to operate transparently, in the sense that you could operate on the file that it points to as if you were accessing the file directly (except of course in the case of rm where of course the link is simply removed).
5 Answers
Symlinks tend to like full paths or relative to the link, otherwise they can often be looking for file-1.txt locally (oddly enough).
Navigate to proper and execute ls -l and you can see that the symlink is looking for actual/file-1.txt, when it should be ../actual/file-1.txt.
So you have two options:
Give the full path
ln -s ~/actual/file-1.txt ~/actual/file-2.txt ~/properNavigate to the folder you want the link to be in and link from there
cd proper ln -s ../actual/file-1.txt ../actual/file-2.txt ./
Edit: A hint to save typing.
You could just do ln -s ~/actual/file-{1,2}.txt ~/proper
The items in the curly braces are substituted and placed after each other, creating the command
ln -s ~/actual/file-1.txt ~/actual/file-2.txt ~/properwhich links both files to the target directory. Saves some major typing as you get further on in the shell.
2The problem is the usage of relative paths. If you specify your link creation with the full explicit path, it works.
$ ln -s ~/actual/file1.txt ~/actual/file2.txt ~/proper/
$ cat proper/file1.txt
file 1
$
Your example creates links in proper that look for a subdirectory named actual under the current directory, rather than your intended parent-of-both.
Symbolic links can be tricky. In essence, a symbolic link is a file that contains a filename/pathname for another file (and that is flagged for special treatment). If the pathname in the link file begins with ‘/’, then it is treated as an absolute pathname, and things are fairly straightforward. If it doesn’t begin with a slash, it is treated as a relative pathname — relative to the directory where the link is located. (This is true whether or not the name contains slashes.) So, you created proper/file–1.txt as a link to “actual/file–1.txt”, and when you tried to access it, the system tried to access proper/actual/file–1.txt. You should have said
ln –s ../actual/file–1.txt ../actual/file–2.txt properBy the way, you didn’t need the touch commands. echo "file 1" > actual/file–1.txt is sufficient to create actual/file–1.txt.
A related issue, and it may be obvious to many, but stumped me for a few minutes: if you're creating a symlink within a directory that is itself symlinked, or there's a symlink within the path of the current working directory, you might run in to problems with symlinks not working.
Use cd .. and ls -l repeatedly, to see if your parent directories are themselves symlinked.
If you need to create a symlink, cd to the original Target directory, and create new symlinks there, so the relative paths are accurate.
Or to put it another way: the relative path is from the Origin to the Target. If the Origin is subsequently symlinked, that's OK. But you might run in to problems setting up a new Origin link_name within a directory that is itself somehow symlinked.
1When you try to create a link to a file that doesn't exist (or you've given the path incorrectly) ln -s doesn't throw an error. It creates a link but when you try 'cat' on that link it says no file found. Even when you can see it using ls. In such cases always double-check your file path.
ubuntu@ip-172-31-80-155:~/lab5$ ln -s etc/ufw/ufw.conf link1
ubuntu@ip-172-31-80-155:~/lab5$ ls -al
total 5360
drwxrwxr-x 2 ubuntu ubuntu 4096 Mar 9 18:56 .
drwxr-xr-x 7 ubuntu ubuntu 4096 Mar 9 18:42 ..
-rwxr--r-- 1 ubuntu ubuntu 5478400 Mar 9 18:32 backup.tar
lrwxrwxrwx 1 ubuntu ubuntu 16 Mar 9 18:56 link1 -> etc/ufw/ufw.conf
ubuntu@ip-172-31-80-155:~/lab5$ cat link1
cat: link1: No such file or directoryBecause the file etc/ufw/ufw.conf doesn't exist. The correct path is /etc/ufw/ufw.conf
ubuntu@ip-172-31-80-155:~/lab5$ ln -s /etc/ufw/ufw.conf link2
ubuntu@ip-172-31-80-155:~/lab5$ ls -l
total 5352
-rwxr--r-- 1 ubuntu ubuntu 5478400 Mar 9 18:32 backup.tar
lrwxrwxrwx 1 ubuntu ubuntu 16 Mar 9 18:56 link1 -> etc/ufw/ufw.conf
lrwxrwxrwx 1 ubuntu ubuntu 17 Mar 9 19:00 link2 -> /etc/ufw/ufw.conf
ubuntu@ip-172-31-80-155:~/lab5$ cat link2
# /etc/ufw/ufw.conf
#
# Set to yes to start on boot. If setting this remotely, be sure to add a rule
# to allow your remote connection before starting ufw. Eg: 'ufw allow 22/tcp'
ENABLED=no
# Please use the 'ufw' command to set the loglevel. Eg: 'ufw logging medium'.
# See 'man ufw' for details.
LOGLEVEL=low 1