Many Unix utilities treat symlinks differently depending on whether there is a trailing slash.
This behavior is described in the POSIX Symbolic Link documentation and is also mentioned in the GNU coreutils documentation.
Basically, the trailing slash means to follow (or "dereference") the symlink.
For example, in the code below, dirlink
means the symlink, but dirlink/
means the directory the symlink points to. rm
won't remove a directory unless you say rm -r
, but rm
without options will happily remove a symlink.
$ mkdir dir
$ ln -s dir dirlink
$ ls -l
total 4
drwxr-xr-x 2 mikel mikel 4096 2011-02-02 22:26 dir
lrwxrwxrwx 1 mikel mikel 3 2011-02-02 22:26 dirlink -> dir
$ ls -l
total 4
drwxr-xr-x 2 mikel mikel 4096 2011-02-02 22:26 dir
lrwxrwxrwx 1 mikel mikel 3 2011-02-02 22:26 dirlink -> dir
$ rm dirlink/
rm: cannot remove `dirlink/': Is a directory
$ rm dirlink
$ ls -l
total 4
drwxr-xr-x 2 mikel mikel 4096 2011-02-02 22:26 dir
It's also useful for viewing the permissions of a directory, without having to bother whether the directory is a real directory or just a symlink to a directory.
$ ls -ld dirlink
lrwxrwxrwx 1 mikel mikel 3 2011-02-02 22:46 dirlink -> dir
$ ls -ld dirlink/
drwxr-xr-x 2 mikel mikel 4096 2011-02-02 22:46 dirlink/
and it still works for regular directories:
$ ls -ld dir
drwxr-xr-x 2 mikel mikel 4096 2011-02-02 22:46 dir
$ ls -ld dir/
drwxr-xr-x 2 mikel mikel 4096 2011-02-02 22:46 dir/
Another example is the find
command. If the path
you ask it to search in is a symlink, it won't follow the symlink by default, meaning it only processes the symlink. Adding a trailing slash makes it treat the symlink as the directory that the link points to.
$ find dir
dir
dir/file
$ find dirlink
dirlink
$ find dirlink/
dirlink/
dirlink/file
(some versions of find have a -follow
or -L
option, but that makes it follow all symlinks, not just the first one)
In the case of rsync
, whether you should append a slash depends on whether you want the directory you're copying to be a subdirectory or not.
$ mkdir dir
$ touch dir/file
$ rsync -r dir dir.bak
$ find .
.
./dir
./dir/file
./dir.bak
./dir.bak/dir
./dir.bak/dir/file
$ rm -r dir.bak
$ rsync -r dir/ dir.bak
$ find .
.
./dir
./dir/file
./dir.bak
./dir.bak/file
In other words:
rsync dir dir.bak
copies dir
into dir.bak
, making dir
inside dir.bak
rsync dir/ dir.bak
copies all the contents of dir
, without making dir
inside dir.bak