4

Я думал, что a и a/. это тот же путь. Однако я обнаружил, что cp и rsync копируют содержимое каталога, а не сам каталог, когда /. добавляется к исходному пути. Я также попытался a/inner/.. ; это тоже помогло.

$ cp -r a b  # Copies dir a into dir b.
$ cp -r a/. b  # Copies files from dir a into dir b.
$ cp -r a/inner/.. b  # Also copies files from dir a into dir b.
$ cd a && cp -r . ../b  # One more way to copy inner files.

Я понимаю, что это полезно. Но я немного запутался, потому что кажется, что эта функция нарушает стандарты.

Как это работает? Эта функция где-то задокументирована? Это особенность ОС, cp или bash?

4 ответа4

1
$ mkdir a b a/inner
$ touch a/a{1..3} b/b{1..3}
$ ls -R
.:
a  b

./a:
a1  a2  a3  inner

./a/inner:

./b:
b1  b2  b3
$ cp a b
cp: omitting directory ‘a’
$ cp a/. b
cp: omitting directory ‘a/.’
$ cp a/inner/.. b
cp: omitting directory ‘a/inner/..’
$ cd a && cp . ../b
cp: omitting directory ‘.’
$ cd ..
$ ls -R
.:
a  b

./a:
a1  a2  a3  inner

./a/inner:

./b:
b1  b2  b3

Ничего из того, что вы говорите, на самом деле не происходит. Четыре команды cp ничего не делают. Возможно, у вас есть псевдоним для загрузки cp . Вы можете проверить это с помощью alias cp .

1

Я понимаю, что это полезно. Но я немного запутался, потому что кажется, что эта функция нарушает стандарты.

поведение cp при рекурсивном копировании из a/. b идеально соответствует его "нормальному" поведению.

По умолчанию cp не создает родительские каталоги. Это можно изменить с помощью переключателя родителей :

   --parents
          use full source file name under DIRECTORY

Но что это значит?

Это означает, что пока команда

cp --parents -r some/path/to/source dest

скопирует содержимое исходного каталога в dest/some/path/to/source , команда

cp -r some/path/to/source dest

скопирует содержимое исходного каталога в dest/source .

Аналогично, команда

cp -r some/path/to/source/. dest

скопирует содержимое исходного каталога в dest/. , который просто dest .

Я подумал и a это тот же путь.

a и a/. это тот же путь. Но в качестве аргумента для cp это просто строка.

Обратите внимание, что команды

cp --parents -r some/path/to/source dest

а также

cd some/path/to && cp --parents -r source dest

будет вести себя по-другому.


Как насчет cp -r a/inner/.. b? Принимая во внимание ваше объяснение, не следует ли копировать файлы в b/.. (т.е. в текущий каталог)?

Ну да. Это исключение.

По крайней мере, в GNU-версии cp есть специальный случай для .. basename.

Из coreutils-8.22/src/cp.c:

          if (parents_option)
            {
              [removed]
            }
          else
            {
              char *arg_base;
              /* Append the last component of 'arg' to 'target_directory'.  */

              ASSIGN_BASENAME_STRDUPA (arg_base, arg);
              /* For 'cp -R source/.. dest', don't copy into 'dest/..'. */
              dst_name = (STREQ (arg_base, "..")
                          ? xstrdup (target_directory)
                          : file_name_concat (target_directory, arg_base,
                                              NULL));
            }

Мотивация, по-видимому, заключается в том, чтобы избегать копирования за пределы целевой папки, что, хотя и идеально согласуется с поведением cp в любом другом случае, немного нелогично и может иметь неприятные последствия.

В конце концов, я не думаю, что кто-то будет ожидать команду

cp -r .. ~

влиять на файлы за пределами его домашнего каталога ...

0

По поводу rsync(1) , внимательно прочитайте его руководство. Он использует некоторые необычные соглашения для обозначения "содержимого каталога" против "каталога и его содержимого".

Для cp(1) и других команд Linux, на уровне ядра a и a/. и даже a/inner/.. ссылаются на точно такой же каталог. Это не означает, что приложение не может разобрать их для себя и дать им разные значения, но проще просто передать строку ядру, которое будет делать правильные вещи.

-1

Если я правильно помню, я верю. в этом случае работает аналогично *. По сути, подстановочный знак.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .