Unix: слеш после имен каталогов или нет

Unix: слеш после имен каталогов или нет

В чем разница между следующими командами?

mv foo bar
mv foo/ bar/
mv foo/ bar
mv foo bar/

Или нет никакой разницы? Или это зависит от используемой команды? Например, я читал, что поведение rsync немного меняется в зависимости от используемой версии. Есть ли у кого-нибудь хорошее объяснение, чтобы мне больше не пришлось гадать и чувствовать, что я знаю, что делаю?

решение1

Многие утилиты Unix по-разному обрабатывают символические ссылки в зависимости от того, есть ли в них завершающий слеш.

Такое поведение описано вДокументация по символическим ссылкам POSIXи также упоминается вДокументация GNU coreutils.

По сути, завершающий слеш означает переход по символической ссылке (или «разыменование»).

Например, в приведенном ниже коде dirlinkозначает символическую ссылку, но dirlink/означает каталог, на который указывает символическая ссылка. rmне удалит каталог, если вы не укажете rm -r, но rmбез параметров успешно удалит символическую ссылку.

$ 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

Это также полезно для просмотра прав доступа к каталогу, не беспокоясь о том, является ли каталог реальным каталогом или просто символической ссылкой на каталог.

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

и это по-прежнему работает для обычных каталогов:

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

Другой пример — findкоманда. Если pathвы просите ее искать в символической ссылке, она не будет следовать по символической ссылке по умолчанию, то есть она будет обрабатывать только символическую ссылку. Добавление завершающего слеша заставляет ее обрабатывать символическую ссылку как каталог, на который указывает ссылка.

$ find dir
dir
dir/file
$ find dirlink
dirlink
$ find dirlink/
dirlink/
dirlink/file

(в некоторых версиях find есть опция -followили -L, но это заставляет ее следовать по всем символическим ссылкам, а не только по первой)


В случае с rsync, необходимость добавления косой черты зависит от того, хотите ли вы, чтобы копируемый каталог был подкаталогом или нет.

$ 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

Другими словами:

  • rsync dir dir.bakкопирует dirв dir.bak, делая dirвнутриdir.bak
  • rsync dir/ dir.bakкопирует все содержимое dir, не делая dirвнутриdir.bak

решение2

Как уже сказал jsalonen, эти команды действительно имеют идентичные результаты, если fooи barпо сути являются каталогами.

Однако, если fooи barне являются каталогами, то команда не будет выполнена, если вы добавите завершающий слеш, и будет выполнена успешно, если вы этого не сделаете. Дело в том, что если команда будет выполнена успешно, она, вероятно, не даст желаемого результата. Фактически, вы даже можете потерять данные, если fooи barявляются файлами ( barбудут перезаписаны).

Если вы намерены указать каталоги, а не файлы, то вамдолжениспользуйте завершающий слеш, так как это делает команду более надежной: если ожидание того, что fooили barявляются каталогами, не выполняется, то команда корректно завершится ошибкой, а не даст неожиданных результатов.

Кроме того, некоторые (редкие) команды ведут себя по-разному в зависимости от наличия завершающего слеша, даже с каталогами (примером является rsync).

Связанный контент