В чем разница между следующими командами?
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
).