Я думал, что a
и a/.
это тот же путь. Однако я обнаружил, чтосри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.
Я понимаю, что это полезно. Но я немного сбит с толку, потому что, похоже, эта функция нарушает стандарты.
Как это работает? Эта функция где-то задокументирована? Это функция ОС,срили баш?
решение1
Я понимаю, что это полезно. Но я немного сбит с толку, потому что, похоже, эта функция нарушает стандарты.
срповедение при рекурсивном копировании из a/.
в b
полностью соответствует его «нормальному» поведению.
По умолчанию,ср's не создает родительские каталоги. Это можно изменить с помощьюродителивыключатель:
--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
иa/.
являетсятот же путь. Но как аргумент кср, это просто строка.
Обратите внимание, что команды
cp --parents -r some/path/to/source dest
и
cd some/path/to && cp --parents -r source dest
также будет вести себя по-другому.
А как насчет
cp -r a/inner/.. b
? Учитывая ваше объяснение, разве не должно оно копировать файлы вb/..
(т.е. в текущий каталог)?
Ну да. Это исключение.
По крайней мере в версии GNUср, существует особый случай для ..
базового имени.
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 -r .. ~
чтобы повлиять на файлы за пределами его домашнего каталога...
решение2
$ 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
.
решение3
Кстати rsync(1)
, прочитайте его руководство.осторожно. Он использует некоторые необычные соглашения для обозначения «содержимого каталога» вместо «каталога и его содержимого».
Для cp(1)
и других команд Linux, вядроlevel a
и a/.
и даже a/inner/..
ссылаются на один и тот же каталог. Это не значит, что приложение не может разобрать их самостоятельно и придать им странные разные значения, но проще просто отправить строку ядру, которое сделает все правильно.
решение4
Если я правильно помню, то, по-моему, в данном случае точка . работает аналогично *. По сути, это подстановочный знак.