cp ведет себя странно, когда. (точка) или .. (точка точка) являются исходными каталогами

Этот ответ показывает, что можно скопировать все файлы, в том числе скрытые, из каталога src в каталог dest:

mkdir dest
cp -r src/. dest

В ответе или его комментариях нет объяснений относительно того, почему это действительно работает, и никто, похоже, не находит документацию по этому поводу.

Я попробовал несколько вещей. Во-первых, нормальный случай:

$ mkdir src src/src_dir dest && touch src/src_file src/.dotfile dest/dest_file
$ cp -r src dest
$ ls -A dest
dest_file  src

Затем с /. в конце:

$ mkdir src src/src_dir dest && touch src/src_file src/.dotfile dest/dest_file
$ cp -r src/. dest
$ ls -A dest
dest_file  .dotfile  src_dir  src_file

Итак, это ведет себя аналогично *, но также копирует скрытые файлы.

$ mkdir src src/src_dir dest && touch src/src_file src/.dotfile dest/dest_file
$ cp -r src/* dest
$ ls -A dest
dest_file  src_dir  src_file

. и .. являются правильными жесткие ссылки как здесь , как и сама запись каталога.

Откуда взялось это поведение и где оно документировано?

10 голосов | спросил iFreilicht 6 WedEurope/Moscow2017-12-06T17:40:26+03:00Europe/Moscow12bEurope/MoscowWed, 06 Dec 2017 17:40:26 +0300 2017, 17:40:26

1 ответ


20

Поведение является логическим результатом документированного алгоритма для cp -R. См. POSIX , шаг 2f:

  

Файлы в каталоге source_file должны быть скопированы в каталог dest_file , взяв перечисленные здесь четыре шага (от 1 до 4) с файлами как source_files .

. и .. являются каталогами , соответственно текущий каталог и родительский каталог. Ни один из них не является особым, насколько это касается оболочки, поэтому ни одна из них не связана с расширением (что позволяет избежать проблем с расширением скрытых файлов оболочки или нет). src/. - текущий каталог внутри src, который src сам; src/src_dir/.. является родительским каталогом src_dir который снова src. Поэтому извне src, если src каталог, указав src/. или src/src_dir/.. как исходный файл для cp эквивалентен и скопировать содержимое src

Точка указания src/. заключается в том, что она не будет выполнена, если src не является каталогом (или символической ссылкой на каталог), тогда как src не будет. Он также скопирует содержимое src, без копирования src; это также соответствует документации:

  

Если существует target и называет существующий каталог, имя соответствующего адресата   путь для каждого файла в иерархии файлов должен быть конкатенацией target , одной косой чертой   символ, если цель не заканчивается косой чертой, а путь к файлу относительно   каталог, содержащий source_file .

So cp -R src/. dest копирует содержимое src to dest/. (исходный файл . in src), тогда как cp -R src dest копирует содержимое src в dest/src ( исходный файл src).

Другой способ подумать об этом - сравнить копирование src/src_dir и src/., а не сравнение src/. и src. . ведет себя точно так же, как src_dir в предыдущем случай.

ответил Stephen Kitt 6 WedEurope/Moscow2017-12-06T17:49:41+03:00Europe/Moscow12bEurope/MoscowWed, 06 Dec 2017 17:49:41 +0300 2017, 17:49:41

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132