Como posso remover todos os diretórios vazios em uma subárvore? Eu usei algo como
find . -type d -exec rmdir {} 2>/dev/null \;
mas preciso executar várias vezes para remover diretórios que contêm apenas diretórios vazios. Além disso, é bastante lento, especialmente no cygwin.
Respostas:
Combinando
find
opções e predicados GNU , este comando deve fazer o trabalho:-type d
restringe a diretórios-empty
restringe aos vazios-delete
remove cada diretórioA árvore é retirada das folhas sem a necessidade de especificar
-depth
como está implícita-delete
.fonte
-delete
já implica-depth
para que você não precise especificar isso manualmente.-mindepth 1
aqui, para impedir a exclusão do próprio diretório inicial, se ele estiver vazio.!
tem um significado especial para o shell. Você precisa escapar disso. Algo como:\! -name 'Completed'
logo antes-delete
deve funcionar. Ou você apenas coloca um arquivo de marcador neste diretório.Liste os diretórios profundamente aninhados primeiro.
(Observe que o redirecionamento se aplica ao
find
comando como um todo, não apenas aormdir
. Redirecionar apenas pararmdir
causaria uma desaceleração significativa, pois você precisaria chamar um shell intermediário.)Você pode evitar a execução
rmdir
em diretórios não vazios, passando o-empty
predicado para localizar. O GNU find testa o diretório quando está prestes a executar o comando, para que os diretórios que acabaram de ser esvaziados sejam escolhidos.Outra maneira de acelerar seria agrupar as
rmdir
invocações. É provável que ambos sejam visivelmente mais rápidos que o original, especialmente no Cygwin. Não espero muita diferença entre esses dois.Qual método é mais rápido depende de quantos diretórios não vazios você possui. Você não pode combinar
-empty
com métodos para agrupar chamadas, porque os diretórios que contêm apenas diretórios vazios não ficam vazios quando osfind
olha.Outro método seria executar várias passagens. Se isso é mais rápido depende de muitas coisas, incluindo se toda a hierarquia de diretórios pode permanecer no cache do disco entre as
find
execuções.Como alternativa, use zsh. O qualificador glob
F
corresponde a diretórios não vazios, portanto,/^F
corresponde a diretórios vazios. Diretórios que contêm apenas diretórios vazios não podem ser correspondidos tão facilmente.(Isso termina quando
rmdir
recebe uma linha de comando vazia.)fonte
-p
? Eu não teria pensado que isso faria diferença.-empty
deve funcionar com esta (embora eu não tenha certeza exatamente quanto ela ganhará). E muito, muito trivialmente, já que você provavelmente não deseja remover.
, use-mindepth 1
.-depth
argumento, o que tornarmdir -p
inútil. Eu já mudei meu comentário. Os anos 90 foram minha tentativa original; não há nada de surpreendente aqui.rmdir
chamada de comando por completo, pelo menos com GNU encontrar, com este comando:find . -depth -type d -empty -delete
Se você apenas colocar um
-p
no seurmdir
, isso funcionará de uma só vez. Não será bonito ou ideal, mas deve ter tudo. Isso diz ao rmdir para remover qualquer diretório-pai não vazio daquele que você está removendo.Você pode economizar um pouco adicionando o
-empty
teste a encontrar, para que ele não se incomode com diretórios não vazios.fonte
find . -depth -type d -exec rmdir {} +
é a resposta mais simples e compatível com esta pergunta.
Infelizmente, as outras respostas fornecidas aqui dependem de aprimoramentos específicos do fornecedor que não existem em todos os sistemas.
fonte
find . -type d -printf "%d %p\n" |\ sort -nr |\ perl -pe 's/^\d+\s//;' |\ while read dir; do \ (rmdir "$dir" > /dev/null 2>&1); \ done
Veja como funciona:
rmdir
na lista, um por umfonte
Eu uso esses aliases para
find
comandos usados com freqüência , especialmente quando eu limpo o espaço em disco usando o dupeguru , onde remover duplicatas pode resultar em muitos diretórios vazios.Comentários lá dentro,
.bashrc
para não esquecê-los mais tarde, quando precisar ajustá-los.fonte
rm -r */
comando funcionou facilmente para mim.rm
deve exigir-f
a remoção forçada de diretórios com arquivos.rm -r
deve remover apenas diretórios vazios. Estou aberto a entender por que isso pode estar errado. Isso também deve deixar os arquivos, pois*/
apenas analisa as pastas.fonte
rm
se destina principalmente a remover arquivos. Embora*/
corresponda apenas aos diretórios, não tenho idéia do que ele faz em níveis mais profundos. Também posso imaginar que ele funciona apenas em alguns sistemas.