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

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

Вопрос:Мне нужен простой пример того, как использовать 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`. (источник)

решение1

По умолчанию 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'

решение2

Вы можете использовать его --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

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

решение3

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

$ 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’

Связанный контент