When should I use a trailing slash on a directory?

58,105

Solution 1

One good example is moving a file into a directory:

mv some_file foo

vs.

mv some_file foo/

If foo doesn't exist, the first will rename some_file to foo, rather than the intended foo/some_file; the second will complain, which is what you want.

If foo does exists but isn't a directory, the first can clobber the foo file; again, the second will complain.

cp presents similar issues.

Working on some old versions of SunOS, I developed the habit of appending /., because the system actually ignored a trailing / on a file name; for example, /etc/motd/ would refer to the file rather than being an error. Later versions of SunOS / Solaris don't seem to have that problem.

Solution 2

It is completely dependent on the tool. rm won't let you remove a symlink to a directory if there's a slash at the end, and rsync does different things if the source file specification has a slash at the end.

Solution 3

foo/ is like foo/., so if foo is a symlink to a directory, foo/ is a directory (not a symlink), and if foo is not a directory or a symlink to a directory, then you get a ENOTDIR error for anything trying to access foo/. That's the behavior on Linux.

Behavior may differ on other systems.

See here and here and here to see what POSIX/SUS have to say about it.

Solution 4

In rsync, the man page reads as follows:

   A trailing slash on the source changes this behavior to avoid  creating
   an  additional  directory level at the destination.  You can think of a
   trailing / on a source as meaning "copy the contents of this directory"
   as  opposed  to  "copy  the  directory  by name", but in both cases the
   attributes of the containing directory are transferred to the  contain-
   ing  directory on the destination.  In other words, each of the follow-
   ing commands copies the files in the same way, including their  setting
   of the attributes of /dest/foo:

          rsync -av /src/foo /dest
          rsync -av /src/foo/ /dest/foo

The trailing slash on the destination doesn't matter at all. Only on the source. (And then, of course, it only matters if the source is a directory rather than a single file or a glob.)

To illustrate the directory to directory use case:

$ mkdir foo bar baz
$ chmod 700 foo
$ chmod 750 bar
$ chmod 705 baz
$ echo hello > foo/file1
$ chmod 606 foo/file1 
$ ls -n
total 0
drwxr-x---  2 501  20   68 Aug  8 15:29 bar/
drwx---r-x  2 501  20   68 Aug  8 15:29 baz/
drwx------  3 501  20  102 Aug  8 15:30 foo/
$ ls -n foo
total 8
-rw----rw-  1 501  20  6 Aug  8 15:30 file1
$ rsync -a foo bar
$ rsync -a foo baz/
$ rsync -a foo bif
$ rsync -a foo bonk/
$ ls -n
total 0
drwxr-x---  3 501  20  102 Aug  8 15:30 bar/
drwx---r-x  3 501  20  102 Aug  8 15:30 baz/
drwxr-xr-x  3 501  20  102 Aug  8 15:30 bif/
drwxr-xr-x  3 501  20  102 Aug  8 15:30 bonk/
drwx------  3 501  20  102 Aug  8 15:30 foo/
$ ls -n *
bar:
total 0
drwx------  3 501  20  102 Aug  8 15:30 foo/

baz:
total 0
drwx------  3 501  20  102 Aug  8 15:30 foo/

bif:
total 0
drwx------  3 501  20  102 Aug  8 15:30 foo/

bonk:
total 0
drwx------  3 501  20  102 Aug  8 15:30 foo/

foo:
total 8
-rw----rw-  1 501  20  6 Aug  8 15:30 file1
$ rm -rf b*
$ mkdir bar baz
$ chmod 750 bar
$ chmod 705 baz
$ rsync -a foo/ bar
$ rsync -a foo/ baz/
$ rsync -a foo/ bif
$ rsync -a foo/ bonk/
$ ls -n
total 0
drwx------  3 501  20  102 Aug  8 15:30 bar/
drwx------  3 501  20  102 Aug  8 15:30 baz/
drwx------  3 501  20  102 Aug  8 15:30 bif/
drwx------  3 501  20  102 Aug  8 15:30 bonk/
drwx------  3 501  20  102 Aug  8 15:30 foo/
$ ls -n *
bar:
total 8
-rw----rw-  1 501  20  6 Aug  8 15:30 file1

baz:
total 8
-rw----rw-  1 501  20  6 Aug  8 15:30 file1

bif:
total 8
-rw----rw-  1 501  20  6 Aug  8 15:30 file1

bonk:
total 8
-rw----rw-  1 501  20  6 Aug  8 15:30 file1

foo:
total 8
-rw----rw-  1 501  20  6 Aug  8 15:30 file1
$ 
Share:
58,105

Related videos on Youtube

Cory Klein
Author by

Cory Klein

Updated on September 18, 2022

Comments

  • Cory Klein
    Cory Klein almost 2 years

    Possible Duplicate:
    How linux handles multiple path separators (/home////username///file)

    Most commands I use in linux behave exactly the same whether I include the trailing slash / character on the end of a directory name or not.

    For example:

    ls /home/cklein
    ls /home/cklein/
    
    cp foo bar
    cp foo/ bar/
    

    When does this trailing slash matter? What is the semantic meaning of the trailing slash?

    • Admin
      Admin over 7 years
      I think the answers here cover the subject okay—it doesn't seem direly in need of new answers—but @djsmith is correct; it's not a duplicate. The other question is related but not at all the same.
    • Admin
      Admin almost 7 years
      Honestly, this isn't a duplicate at all. This is about trailing slashes on a directory, not multiple consecutive slashes. I just wrote a good test case with rsync that I want to post here for illustration of the different cases, but I can't until the question is reopened.
    • Admin
      Admin almost 7 years
      Agreed - I added my nomination to reopen.
    • Admin
      Admin almost 7 years
      I've reopened because unix.stackexchange.com/questions/870/… is a better duplicate.
    • Admin
      Admin almost 7 years
      Since you're still around, would you mind at least not accepting a one-liner answer that didn't even get its meager facts right?
  • Hugo
    Hugo over 11 years
    Pay very close attention when using rsync!!! The trailing slash really matters.
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' over 11 years
    For the most part, a trailing / means “treat this as a directory, dereference the symlink if it is one, complain if it isn't a directory”. This behavior is mandated for utilities specified by POSIX. Rsync's source argument is a notable exception.
  • chrisfargen
    chrisfargen over 10 years
    Note that by default, chown -R /dir1/symlink1 will not perform recursion when the target is a symbolic link; however, chown -R /dir1/symlink1/ will do what you would expect.
  • Anthony Geoghegan
    Anthony Geoghegan over 7 years
    I've edited the first two links to POSIX specifications but I'm not fully confident about the third link - which I presume should be to pubs.opengroup.org/onlinepubs/9699919799/xrat/…
  • Stéphane Chazelas
    Stéphane Chazelas over 7 years
    Thanks. Yes it's annoying that the TC2 update is now available at the same URL as the previous versions but with completely different HTML anchors. Many of the links are even broken there, so I'd expect it will change again. Might be better to link to the web archive to get consistent links.
  • Wildcard
    Wildcard almost 7 years
    This answer says "rsync does different things if the remote file specification has a slash at the end," but it appears that it's really only if the source file specification has a slash that you get different behavior - right? It doesn't seem to matter whether there is or isn't a slash on the destination directory, regardless of which file (if any) is remote. Or am I missing something? (Also @Gilles.)
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' almost 7 years
    @Wildcard Yes, with rsync, a trailing / matters for source files. It doesn't matter whether the file is remote.
  • Alessio
    Alessio almost 7 years
    +1. I use rsync all the time and have done so for many years, and I can still never remember the exact details of rsync's handling of a trailing slash on the source dir. I always have to --dry-run it first or read the man page. It's good to see this answer, but it's unlikely to fix my memory :(