cp --no-target-directory explicado

10

Pergunta: Eu preciso de um exemplo simples de como usar cp --no-target-directory.

Eu tenho algumas dificuldades em entender cp --no-target-directory. Entendo a explicação paramv --no-target-directory , mas não consigo imaginar uma maneira de usá-la cp.

Por exemplo, quando o comando mv /tmp/source /tmp/desté bem-sucedido, não há garantia que /tmp/sourcefoi renomeada para /tmp/dest: ela poderia ter sido renomeada /tmp/dest/source, se algum outro processo fosse criado /tmp/destcomo um diretório. No entanto, se mv -T /tmp/source /tmp/destfor bem-sucedido, não há dúvida de que /tmp/source was renamed to/ tmp / dest`. ( fonte )

erch
fonte

Respostas:

15

Por padrão, cptesta se seu último argumento é um diretório existente. Se isso acontecer, cpcria um link dentro desse diretório, com o nome base da fonte. Ou seja, dado o comando

cp foo/bar wibble

if wibbleé um diretório existente, cpcopia a fonte para wibble/bar. Se wibblenão existir, cpvincule a fonte a wibble.

Se você quiser ter certeza de que a cópia é sempre wibble, poderá especificar a opção --no-target-directory(alias -T). Dessa forma, se cpfor bem-sucedido, você pode ter certeza de que a cópia é chamada wibble. Se wibblejá existir como um diretório, cpfalhará.

Em forma de tabela:

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

A única diferença é que -T, caso o destino seja um diretório existente, o comando retornará um erro. Isso é útil quando você espera que o diretório não exista: você recebe uma mensagem de erro em vez de algo imprevisível.

O mesmo se aplica a mve ln. Se o destino for um diretório existente, com -T, eles sinalizam um erro, em vez de fazerem algo diferente silenciosamente.

Com cp, há um caso diferente. Se você fizer uma cópia recursiva e a fonte for um diretório, cp -Tcopie o conteúdo da fonte no destino, em vez de copiar a própria fonte. Ou seja, dado

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

então

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

enquanto que

% cp -rvT source destination
`source/foo' -> `destination/foo'
Gilles 'SO- parar de ser mau'
fonte
8

Você usaria --no-target-directoryse não quisesse que um diretório de origem fosse copiado sob um diretório de destino existente, e que o diretório de origem fosse copiado para o diretório de destino.

Aqui está um exemplo de uma cópia de diretório com e sem --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

Você pode conseguir algo do mesmo efeito sufixando o nome do diretório fonte (s) com barra-ponto /.como em: cp -r a/. bqual diretório fonte cópias a para b e não por baixo b .

Nenhum dos métodos acima é o mesmo que dizer "copie apenas o conteúdo do diretório de origem para o destino existente", pois, se você pedir para preservar a hora e as permissões, o diretório de destino existente adquirirá a hora e as permissões do diretório de origem. Um exemplo (editado para remover informações desnecessárias):

$ 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

Uma cópia somente de conteúdo não transfere o modo ou os carimbos de data e hora do diretório de origem para o diretório de destino.

Ian D. Allen
fonte
2

Que tal o seguinte?

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

Como tal, é apenas uma maneira diferente de escrever cp Dir_1/* Dir_2/. No entanto, ele captura arquivos ocultos na raiz de Dir_1 que seriam perdidos por um simples 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’
Railgun2
fonte
funciona para mim com a --no-target-directoryopção [out] : desde que eu use --recursive, está tudo bem [ coreutils 8.12no GNU / Linux]. A principal diferença parece ser que com --no-target-directoryo conteúdo, mas não o próprio diretório é copiado [pesquisa ainda em andamento]
erch