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 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

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).