Por que foi encontrado com -delete apagar os arquivos no meu diretório / save / quando o find without delete não conseguiu localizá-los?

20

Desejo excluir todos os arquivos na árvore de diretórios atual, exceto os que estão em save . Eu corri este comando:

 find . \( -name save -prune \) -o -type f -ls | grep /save/

e não encontrou nenhum. Mas quando eu corri este comando:

 find . \( -name save -prune \) -o -type f -delete

Todos esses arquivos em / save / foram eliminados. O que estou perdendo?

    
por Otheus 21.01.2016 / 11:23

1 resposta

26

-delete implica -depth que não funciona com -prune ( -depth começa com as folhas). Há um aviso sobre isso no manual da versão GNU ( -delete é uma extensão do FreeBSD agora também suportada pelo GNU find e algumas outras implementações).

info find --index-search=-delete

The use of the '-delete' action on the command line automatically turns on the '-depth' option (*note find Expressions::). This can be surprising if you were previously just testing with '-print', so it is usually best to remember to use '-depth' explicitly.

info find --index-search=-prune

Because '-delete' implies '-depth', using '-prune' in combination with '-delete' may well result in the deletion of more files than you intended.

Aqui, você tem a opção de usar rm :

find . -name save -prune -o -type f -exec rm -f {} +

(potencialmente inseguro se houver um diretório gravável por outras pessoas, como se fosse possível excluir arquivos fora da árvore de diretórios atual, substituindo diretórios por links simbólicos enquanto você executa esse comando).

Uma alternativa mais segura:

find . -name save -prune -o -type f -execdir rm -f -- {} \;

Isso não tem o problema mencionado acima, mas significa executar um rm por arquivo. O -- é necessário para a implementação do FreeBSD, não para o GNU, que prefixa os nomes dos arquivos com ./ .

Alternativamente, como sugerido por Costas:

LC_ALL=C find . ! -name save ! -path '*/save/*' -type f -delete

(mas isso ainda desce desnecessariamente em save diretórios)

O LC_ALL=C está lá, então * corresponde a qualquer seqüência de bytes (mesmo aqueles que não formam caracteres válidos na localidade atual). Observe que isso afetará o idioma das mensagens de erro (inglês em vez do idioma do usuário).

    
por 21.01.2016 / 11:31

Tags