Qual é o valor agregado da opção -T no GNU cp e mv?

26

Por que alguns comandos do GNU Coreutils têm a -T/--no-target-directoryopção? Parece que tudo o que faz pode ser alcançado usando a semântica do .(ponto próprio) em uma hierarquia de diretórios Unix tradicional.

Considerando:

cp -rT /this/source dir

A -Topção impede que a cópia crie um dir/sourcesubdiretório. Em vez disso, /this/sourceé identificado dire o conteúdo é mapeado entre as árvores de acordo. Então, por exemplo, /this/source/foo.cvai dir/foo.ce assim por diante, ao invés de dir/source/foo.c.

Mas isso pode ser facilmente realizado sem a -Topção usando:

cp -r /this/source/. dir  # Probably worked fine since dawn of Unix?

Semanticamente, o componente de ponto final é copiado como filho de dir, mas é claro que "filho" já existe (portanto, não precisa ser criado) e é realmente direle próprio; portanto, o efeito é o /this/pathidentificado dir.

Funciona bem se o diretório atual for o destino:

cp -r /this/tree/node/. . # node's children go to current dir

Existe algo que você pode fazer única com -Tque pode racionalizar a sua existência? (Além do suporte para sistemas operacionais que não implementam o diretório de pontos, uma justificativa não mencionada na documentação.)

O truque de pontos acima não resolve as mesmas condições de corrida mencionadas na documentação sobre o GNU Info -T?

Kaz
fonte

Respostas:

29

Seu .truque só pode ser usado quando você está copiando um diretório, não um arquivo. A -Topção funciona com diretórios e arquivos. Se você fizer:

cp srcfile destfile

e já existe um diretório chamado destfilepara o destfile/srcfilequal ele será copiado , o que pode não ser o pretendido. Então você usa

cp -T srcfile destfile

e você recebe corretamente o erro:

cp: cannot overwrite directory `destfile' with non-directory

Se você tentasse usar o .método, a cópia nunca funcionaria:

cp: cannot stat `srcfile/.`: Not a directory
Barmar
fonte
O .truque faz o trabalho ao copiar um arquivo, não apenas quando renomear seu nome base, ao mesmo tempo! cp /path/to/file /target/dir/. Se /target/dir/fileexiste e é um diretório, você obtém o mesmo diagnóstico! Mas você mostrou o -Tque isso não pode ser feito sem ele em uma etapa, sem condições de corrida: copie um arquivo e altere seu nome sem que ele seja desviado para um subdiretório.
Kaz
3
Isso não é o mesmo - o .truque que você está falando está anexando /.à fonte .
Barmar
21

O problema com cp/ mv/ lncomo eles foram projetados originalmente é que eles são dois comandos em um ( copiar e copiar ).

cp A B

é copiar A para B ou copiar A para B ( copiar A para B / A ), dependendo de Bexistir ou não ser um diretório (e mais variações se B for um link simbólico para um diretório).

Isso é ruim porque é ambíguo. Portanto, as implementações do GNU adicionaram opções para contornar isso.

cp -T A B

copia de A a B independentemente. Se Bexistir e for um diretório, isso falhará (a menos que você passe -r). Em qualquer caso, você não terminará com um Aarquivo Bquando pretender Aser copiado para B.

E:

cp -t B A

é a cópia para .

Stéphane Chazelas
fonte
A filosofia original do unix é assumir que você sabe o que faz e, felizmente, permitirá que você atire no próprio pé.
Lenne
4
@Lenne, mas aqui não dá uma maneira de evitar dar um tiro no próprio pé. Se alguém criar um diretório B ou um link simbólico para algum diretório antes de você executar cp A Bo comando, não fará o que você pretendia. E fazer [ -e B ] || [ -L B ] || cp A Bainda tem uma condição de corrida que cp -Tn A Bnão tem.
Stéphane Chazelas
6

O -Tpode fornecer uma falha se um diretório existir incorretamente para o que deve ser um arquivo de destino:

$ mkdir mustbeafile
$ touch afile
$ cp -T afile mustbeafile
cp: cannot overwrite directory `mustbeafile' with non-directory
$ echo $?
1
$ cp afile mustbeafile
$ 

Ou seja, em vez de obter êxito em uma cópia inesperada em um subdiretório, ocorre um status de aviso e de saída não boa, que pode causar o cancelamento de um script e inspecionar por que um diretório não deveria ser Seja um.

agitar
fonte
0

O uso de um sinalizador também é muito mais claro e tem menos risco de efeitos indesejados, quando o comando é usado em um script em vez de inserido manualmente. A aplicação de pontos nos caminhos de um script pode acabar em todos os tipos de travessuras inesperadas.

rackandboneman
fonte