Unix: Slash after directory names or not
What is the difference between the following commands?
mv foo bar
mv foo/ bar/
mv foo/ bar
mv foo bar/
Or is there no difference? Or does it depend on the command being used? Think for example I read that the rsync behavior changes a bit depending on which version you use. Does anyone have a good explanation so I don't have to guess anymore and feel like I know what I'm doing?
Solution 1:
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
copiesdir
intodir.bak
, makingdir
insidedir.bak
-
rsync dir/ dir.bak
copies all the contents ofdir
, without makingdir
insidedir.bak
Solution 2:
As jsalonen already said, these commands indeed have identical results if foo
and bar
are, as a matter of fact, directories.
However, if foo
and bar
are not directories, then the command will fail if you append a trailing slash, and will succeed if you don't. Thing is, if the command succeeds, it'll probably not have the result you intended. In fact, you could even lose data if foo
and bar
are files (bar
would be overwritten).
If your intention is to specify directories and not files, then you should use a trailing slash, because it makes the command more robust: if the expectation that foo
or bar
are directories fails, then the command will fail gracefully, instead of having unexpected results.
Also, some (rare) commands behave differently depending of the presence of a trailing slash, even with directories (one example is rsync
).