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

8

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

cp -rfva ../foldersource/. ./

mas isso funciona também

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, o asterisco é melhores opções que funcionam em qualquer lugar?

stackdave
fonte

Respostas:

10

Há 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, se é cpou rmou qualquer outra coisa. Depende do comando se esse ponto à direita possui semântica especial ou única diferente da convenção padrão do Unix de simplesmente apontar para o diretório em que ele reside; ambos rme cpparecem tratá-lo como um caso especial.

Com ../foldersource/*o argumento é expandido primeiro pelo shell antes que o comando seja sequer executado e passado quaisquer argumentos. Assim, rmnunca vê ../foldersource/*; vê a versão expandida ../foldersource/file1.ext ../foldersource/file2.ext ../foldersource/childfolder1e assim por diante. Isso é importante porque os sistemas operacionais limitam quantos argumentos podem ser passados ​​para um comando, geralmente apenas algumas centenas.

eestrada
fonte
4
It's up to the command whether that trailing dot makes any senseHum, o ponto sempre está vinculado ao próprio diretório, portanto ../foldersource/., não deve ser diferente de declarar ./foldersource/e, de fato, é apenas uma maneira redundante de afirmar a mesma coisa. Nenhum comando tenta "entender" o ponto ou o ponto duplo, pois estes são padrão nos sistemas de arquivos Linux / Unix. rmsimplesmente rejeita a remoção do diretório de trabalho atual, conforme jimmijindicado na resposta. Além disso, observe que você está usando ./em todos os seus exemplos enquanto o OP está ../lá. Um pouco de (grande) diferença.
Sergiy Kolodyazhnyy
"cp -rfva ../foldersource/ ./" é equivalente a "cp -rfva ../foldersource ./", eu quero copiar o conteúdo foldersource, mas não a raiz pasta
stackdave
1
@Stackdave não, cp -rfva ../foldersource/. ./ NÃO é equivalente a cp -rfva ../foldersource ./ . O arrasto /.é significativa
roaima
2
Enquanto o que esta resposta diz está correto, está faltando uma diferença muito importante, como mencionado na resposta do @ roaima: a variante / * (geralmente) não copia arquivos ou diretórios começando com.
Adam
@SergiyKolodyazhnyy Você está certo; Essa .é uma convenção padrão no Unix para denotar a corrente diretamente. Além disso, obrigado por apontar que eu tinha usado ./nos meus exemplos quando deveria ter usado ../; Eu vou consertar isso. Você está incorreto sobre se os comandos "fazem sentido" do ponto à direita; como o OP aponta (e eu já experimentei cp) ambos rme cpse comporta de maneira diferente quando um rastro .está presente. Eu deveria ter escrito algo como "cabe ao comando se o ponto à direita tiver semântica especial ou única". Vou mudar minha resposta para maior clareza.
eestrada
10

Ao copiar usando, cp -a source/* target/você está copiando a maioria dos arquivos e diretórios de sourcepara target. Especificamente, os itens excluídos provavelmente serão arquivos começando 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 source, incluindo itens que começam com um ponto ( .) paratarget

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, zshpoderá usar a dotglobopção para alterar o significado de, *para que ele inclua arquivos e diretórios que começam com um ponto ( yashtambém tem uma dotglobopção; no entanto, ele inclui .e ..em expansões globais que limitam sua usabilidade. FIGNORE='@(.|..)'in ksh93).

Curiosamente, cp -a source/. target/é garantido nunca criar o componente target/source. (Por outro lado, cp -a source target/fará uma de duas coisas, dependendo da sua existência ou não target. Consulte Como copiar uma pasta recursivamente de maneira idempotente usando cp para obter detalhes.)


Ao excluir usando, rm -rf source/*você exclui os arquivos e diretórios dentro deles sourceque não começam com um ponto ( .). Sujeito à dotglobconfiguração que eu já mencionei. Não excluirá o sourcepróprio diretório .

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

roaima
fonte
1
Consulte também 'rm. *' Já exclui o diretório pai? sobre rm -rf .falhar .
Stéphane Chazelas
7

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

Qualquer tentativa de remover um arquivo cujo último componente do nome do arquivo seja '.' ou '..' é rejeitado sem aviso, conforme exigido pelo POSIX.

e no manual POSIX man 1p rm, vemos:

Se um dos arquivos ponto ou ponto estiver especificado como a parte do nome de base de um operando (ou seja, o componente final do nome do caminho) ou se um operando for resolvido para o diretório raiz, a rm escreverá uma mensagem de diagnóstico para erro padrão e não fará nada mais com esses operandos.

jimmij
fonte