diferença copiar a pasta de conteúdo entre /. e / * no linux

7

para copiar o conteúdo de uma pasta que eu li, o uso é:

cp -rfva ../foldersource/. ./

mas isso também funciona

cp -rfva ../foldersource/* ./

existe alguma diferença?

por exemplo, se eu quiser excluir um conteúdo de uma pasta com. :

rm -rf ../foldersource/.

eu recebo o erro:

rm:  rejet delete folder '.' or '..':

mas com asterisco está ok

rm -rf ../foldersource/*

Então, asterisco são melhores opções que funcionam em qualquer lugar?

    
por stackdave 23.07.2017 / 20:07

3 respostas

8

Existe uma diferença fundamental entre essas duas formas de argumento. E é importante entender o que está acontecendo.

Com ../foldersource/. , o argumento é passado inalterado para o comando, seja cp ou rm ou qualquer outra coisa. Cabe ao comando se esse ponto final tem uma semântica especial ou única diferente da convenção padrão do Unix de simplesmente apontar para o diretório em que reside; os dois rm e cp parecem tratá-lo como um caso especial.

Com ../foldersource/* , o argumento é primeiro expandido pelo shell antes de o comando ser executado e passar qualquer argumento. Assim, rm nunca vê ../foldersource/* ; ele vê a versão expandida ../foldersource/file1.ext ../foldersource/file2.ext ../foldersource/childfolder1 e assim por diante. Isso é importante porque os sistemas operacionais limitam quantos argumentos podem ser passados para um comando, geralmente apenas algumas centenas.

    
por 23.07.2017 / 23:03
10

Quando você copia usando cp -a source/* target/ , está copiando a maioria dos arquivos e diretórios de source para target . Especificamente, os itens excluídos provavelmente serão arquivos que começam com um ponto ( . ) no nível superior de source .

Considere esses arquivos (ou diretórios) em source

apple        # will be copied
banana/      # will be copied, as will all its contents
.cherry      # will not be copied

Ao copiar usando cp -a source/. target/ , você está copiando todo o conteúdo de source , incluindo todos os itens que começam com um ponto ( . ) para target

Considere esses arquivos (ou diretórios) em source

apple        # will be copied
banana/      # will be copied, as will all its contents
.cherry      # will be copied

Se você estiver usando bash , zsh , poderá usar o dotglob option para alterar o significado de * para que inclua arquivos e diretórios que começam com um ponto ( yash também tem uma opção dotglob ; no entanto, ele inclui . e .. em expansões glob que limitam sua usabilidade. Veja também FIGNORE='@(.|..)' in ksh93 ).

Curiosamente, cp -a source/. target/ é garantido never para criar o componente target/source . (Por outro lado, cp -a source target/ fará uma das duas coisas dependendo se a target já existe ou não. Consulte Como copiar uma pasta recursivamente de uma maneira idempotente usando cp para os detalhes.

Quando você exclui usando rm -rf source/* , está excluindo os arquivos e diretórios no source que não começam com um ponto ( . ). Sujeito à configuração dotglob que já mencionei. Ele não excluirá o diretório source em si.

Quando você tenta excluir usando rm -rf source/. , ele falhará - como outros já explicaram - porque POSIX proíbe a exclusão de um caminho cujo último componente seja . ou .. . O equivalente mais próximo é rm -rf source , que excluirá o diretório source e todo o seu conteúdo, independentemente de começarem ou não com um ponto ( . ).

    
por 23.07.2017 / 23:33
7

Você não pode fazer rm -rf ../foldersource/. porque rm não permite isso, conforme explicitamente indicado no manual:

Any attempt to remove a file whose last file name component is ‘.’ or ‘..’ is rejected without any prompting, as mandated by POSIX.

e no manual do POSIX man 1p rm , vemos:

If either of the files dot or dot-dot are specified as the basename portion of an operand (that is, the final pathname component) or if an operand resolves to the root directory, rm shall write a diagnostic message to standard error and do nothing more with such operands.

    
por 23.07.2017 / 21:10

Tags