cp --no-target-directory объяснил


10

Вопрос: мне нужен простой пример того, как использовать cp --no-target-directory.

Я испытываю некоторые трудности в понимании cp --no-target-directory. Я понимаю объяснениеmv --no-target-directory , но я не могу себе представить, как его использовать cp.

Например, когда команда выполнена mv /tmp/source /tmp/destуспешно, нет гарантии, что она /tmp/sourceбыла переименована /tmp/dest: /tmp/dest/sourceвместо этого ее можно было бы переименовать , если какой-либо другой процесс был создан /tmp/destкак каталог. Однако, если это mv -T /tmp/source /tmp/destудастся, нет сомнений, что /tmp/source was renamed to/ tmp / dest`. ( источник )

Ответы:


15

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

cp foo/bar wibble

Если wibbleэто существующий каталог, то cpкопирует источник в wibble/bar. Если wibbleне существует, то cpссылки на источник wibble.

Если вы хотите быть уверены, что копия всегда wibble, тогда вы можете указать опцию --no-target-directory(псевдоним -T). Таким образом, в случае cpуспеха вы можете быть уверены, что копия вызывается wibble. Если wibbleкаталог уже существует, cpпроизойдет сбой.

В табличной форме:

The target is …             Without -T               With -T
existing directory          copy in the directory    error
existing file (not dir)     overwrite                overwrite
does not exist              create                   create

Единственное отличие состоит в том -T, что в случае, если целью является существующий каталог, команда возвращает ошибку. Это полезно, когда вы ожидаете, что каталог не существует: вы получите сообщение об ошибке вместо чего-то непредвиденного.

То же самое относится mvи к ln. Если целью является существующий каталог, -Tони сообщают об ошибке, а не молча делают что-то другое.

С cp, есть другой случай. Если вы делаете рекурсивное копирование, а источник является каталогом, то cp -Tкопирует содержимое источника в место назначения, а не копирует сам источник. То есть дано

$ tree source destination 
source
└── foo
destination
└── bar

тогда

$ cp -rv source destination
`source' -> `destination/source'
`source/foo' -> `destination/source/foo'

в то время как

% cp -rvT source destination
`source/foo' -> `destination/foo'

8

Вы могли бы использовать , --no-target-directoryесли вы не хотите , исходный каталог скопированный под существующий каталог назначения, вы хотите , чтобы исходный каталог скопирован на директорию назначения.

Вот пример копии каталога с и без --no-target-directory:

$ mkdir a
$ touch a/b a/c
$ find
.
./a
./a/c
./a/b
$ cp -r a b       # b does not exist; becomes copy of a
$ find
.
./b
./b/b
./b/c
./a
./a/c
./a/b
$ rm -r b
$ mkdir b
$ cp -r a b       # b already exists; a is copied *underneath* it
$ find
.
./b
./b/a
./b/a/b
./b/a/c
./a
./a/c
./a/b
$ rm -r b
$ mkdir b
$ cp -r --no-target-directory a b     # b already exists; becomes copy of a
$ find
.
./b
./b/b
./b/c
./a
./a/c
./a/b

Вы можете достичь чего - то одного и того же эффекта с помощью суффикса имени исходного каталога (ы) с слэш-точка , /.как в: cp -r a/. bкакой каталоге копии исходного a на b и не под b .

Ни один из вышеперечисленных методов не отличается от того, что говорится «копировать только содержимое исходного каталога в существующий пункт назначения», поскольку, если вы попросите сохранить время и разрешения, существующий каталог назначения получит время и разрешения для исходного каталога. Пример (отредактированный для удаления ненужной информации):

$ find . -ls
drwx------   Oct 13 13:31 ./b         # note date and permissions
drwxr-xr-x   Jan  1  2013 ./a         # note date and permissions
-rw-r--r--   Oct 13 13:23 ./a/c
-rw-r--r--   Oct 13 13:23 ./a/b
$ cp -rp --no-target-directory a b    # preserve mode and timestamps
$ find . -ls
drwxr-xr-x   Jan  1  2013 ./b         # note copied date and permissions
-rw-r--r--   Oct 13 13:23 ./b/b
-rw-r--r--   Oct 13 13:23 ./b/c
drwxr-xr-x   Jan  1  2013 ./a
-rw-r--r--   Oct 13 13:23 ./a/c
-rw-r--r--   Oct 13 13:23 ./a/b

Копия только для содержимого не будет передавать режим или временные метки исходного каталога в целевой каталог.


2

Как насчет следующего?

$ cp -rvT Dir_1 Dir_2
‘Dir_1/File_3.txt’ -> ‘Dir_2/File_3.txt’
‘Dir_1/File_1.txt’ -> ‘Dir_2/File_1.txt’
‘Dir_1/File_2.txt’ -> ‘Dir_2/File_2.txt’
$ cp -rv Dir_1 Dir_2
‘Dir_1’ -> ‘Dir_2/Dir_1’
‘Dir_1/File_3.txt’ -> ‘Dir_2/Dir_1/File_3.txt’
‘Dir_1/File_1.txt’ -> ‘Dir_2/Dir_1/File_1.txt’
‘Dir_1/File_2.txt’ -> ‘Dir_2/Dir_1/File_2.txt’

Таким образом, это просто другой способ написания cp Dir_1/* Dir_2/. Тем не менее, он ловит скрытые файлы в корне Dir_1, которые будут пропущены простым cp *.

$ touch Dir_1/.Hidden_File_{1,2,3}.txt
$ cp -rv Dir_1/* Dir_2
cp: No match.
$ cp -rvT Dir_1 Dir_2
‘Dir_1/.Hidden_File_2.txt’ -> ‘Dir_2/.Hidden_File_2.txt’
‘Dir_1/.Hidden_File_3.txt’ -> ‘Dir_2/.Hidden_File_3.txt’
‘Dir_1/.Hidden_File_1.txt’ -> ‘Dir_2/.Hidden_File_1.txt’

у меня работает с --no-target-directoryопцией [out] : пока я использую --recursive, все в порядке [с coreutils 8.12GNU / Linux]. Основное различие заключается в том, что --no-target-directoryкопируется содержимое, а не сам каталог [исследования продолжаются]
erch
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.