Como apagar diretórios com base na saída 'find'?

105

Emita o seguinte comando para encontrar os diretórios .svn:

find . -name ".svn"

Isso me dá os seguintes resultados:

./toto/.svn
./toto/titi/.svn
./toto/tata/.svn

Como eu poderia processar todas essas linhas com rm -fr para excluir os diretórios e seu conteúdo?

    
por Super Chafouin 09.09.2013 / 10:34

7 respostas

141

Find pode executar argumentos com a opção -exec para cada correspondência que encontrar. É um mecanismo recomendado porque você pode manipular caminhos com espaços / novas linhas e outros caracteres corretamente. Você terá que excluir o conteúdo do diretório antes de poder remover o próprio diretório, portanto, use -r com o comando rm para conseguir isso.

Para o seu exemplo, você pode emitir:

find . -name ".svn" -exec rm -r "{}" \;

Você também pode dizer ao find para encontrar apenas diretórios chamado .svn, adicionando um -type d check:

find . -name ".svn" -type d -exec rm -r "{}" \;

Aviso Use rm -r com cuidado para excluir a pasta e todo o seu conteúdo.

Se você quiser excluir somente diretórios vazios, bem como diretórios que contenham apenas diretórios vazios, o find pode fazer isso com -delete e -empty :

find . -name ".svn" -type d -empty -delete
    
por 09.09.2013 / 12:00
54

Aqui está um portátil ainda mais rápido que o modo de resposta aceito.

Usar um + em vez de um ponto-e-vírgula como o find do terminador de comando está otimizando o uso da CPU. Isso pode ser significativo se você tiver muitos sub-diretórios .svn :

find . -name .svn -type d -exec rm -rf {} +

Note também que você nunca 1 precisa citar as chaves aqui.

1 A menos que você use o fish shell.

    
por 09.09.2013 / 13:04
26

Suponha que você esteja usando o find do gnu , você pode usar a opção -delete :

find . -name test -delete

que é mais fácil de lembrar.

    
por 11.08.2014 / 00:54
9

No meu computador quando uso:

find . \( -name dirname -type d \) -exec rm -r '{}' ';'

Os diretórios são excluídos, mas recebo o erro:

find: ‘./dirname’: No such file or directory

para cada diretório.

Meus diretórios não estão vazios, então a opção -delete não funcionará para mim. Eu encontrei a razão para este comportamento aqui :

  1. find takes (not necessarily) the first entry in the ./ directory. this would be e.g. dir.1/
  2. it compares it to the pattern 'dir.?'. does it match? yes.
  3. find executes "rm -r dir.1".
  4. find tries to enter dir.1/ to find the pattern within the directory. it doesn't know anything about the exec command.
  5. it doesn't find dir.1/ anymore. returns ENOENT (look at the strace output)

Eu usei isso para resolver:

rm -r 'find . -name dirname -type d'

Tenha em mente que o find ainda tentará recorrer aos diretórios chamados dirname, o que não é realmente necessário e levará algum tempo adicional. Dependendo da sua estrutura de diretórios, você poderá contornar isso com a opção --depth find. Além disso, se você tiver uma estrutura de diretórios como dirname / foo / dirname, obterá erros "No such file or directory" de rm. Para suprimir os erros, você pode redirecionar stderr para / dev / null ou usar o sinalizador -f (force) com rm.

    
por 07.10.2015 / 19:18
9

Uma maneira mais rápida de fazer isso é:

find . -name ".svn" -type d -prune -exec rm -rf '{}' '+'

No caso de você ter ".svn" dentro de outro ".svn".

    
por 11.07.2016 / 02:34
5

Solução específica de bash:

shopt -s globstar
rm -r **/.svn
shopt -u globstar #optional. this will disable globstar expansion
    
por 09.09.2013 / 12:00
4

Descobri que a ação -delete funciona bem com o teste -path . Por exemplo, o seguinte deve funcionar no problema dos pôsteres originais:

find . -path '*/.svn*' -delete
    
por 21.02.2017 / 12:22