Qual é a maneira mais rápida de remover todos os arquivos e subpastas de um diretório? [duplicado]

15

Um programa criou muitas subpastas aninhadas. Tentei usar o comando   rm -fr * para removê-los todos. Mas é muito lento. Eu estou querendo saber se existe alguma maneira mais rápida de excluir todos eles?

    
por Lei Hao 18.04.2016 / 09:33

4 respostas

19

A maneira mais rápida de removê-los desse diretório é movê-los para fora de lá, depois disso, basta removê-los em segundo plano:

mkdir ../.tmp_to_remove
mv -- * ../.tmp_to_remove
rm -rf ../.tmp_to_remove &

Isso pressupõe que seu diretório atual não é o nível superior de alguma partição montada (por exemplo, ../.tmp_to_remove está no mesmo sistema de arquivos).

O -- após mv (como editado por Stéphane) é necessário se você tiver qualquer nome de arquivo / diretório começando com - .

O texto acima remove os arquivos do diretório atual em uma fração de segundo, já que ele não precisa manipular recursivamente os subdiretórios. A remoção real da árvore do sistema de arquivos leva mais tempo, mas, como está fora do caminho, sua eficiência real não deve importar muito.

    
por 18.04.2016 / 10:55
11

rsync é surpreendentemente rápido e simples. Você tem que criar um diretório vazio primeiro,

mkdir emptydir
rsync -a --delete emptydir/ yourdirectory/

yourdirectory/ é o diretório de onde você deseja remover os arquivos.

    
por 18.04.2016 / 09:49
9

Um problema com rm -rf * , ou seu equivalente mais correto rm -rf -- * é que o shell tem que listar todos os arquivos (não ocultos) no diretório atual, classificá-los e passá-los para rm , que se a lista de arquivos no diretório atual for grande, isso adicionará alguma sobrecarga extra desnecessária e poderá até falhar se a lista de arquivos for muito grande.

Normalmente, você faria rm -rf . (o que também teria o benefício de excluir arquivos ocultos também). Mas a maioria das implementações rm , incluindo todas as em conformidade com POSIX, recusarão fazê-lo. A razão é que alguns shells (incluindo todos os POSIXs) têm um erro na especificação de que a expansão de .* glob incluiria . e .. . O que significaria que rm -rf .* excluiria o diretório atual e o diretório pai, portanto, rm foi modificado para contornar essa má especificação desses shells.

Alguns shells como pdksh (e outros derivados shell de Forsyth), zsh ou fish não têm esse tipo de falha. zsh tem rm embutido que você pode ativar com autoload zsh/files , pois zsh .* não inclui . nem .. funciona OK com rm -rf . . Então, em zsh , você pode fazer:

autoload zsh/files
rm -rf .

No Linux, você pode fazer:

rm -rf /proc/self/cwd/

para esvaziar o diretório atual ou:

rm -rf /dev/fd/3/ 3< some/dir

para esvaziar um diretório arbitrário.

(observe o trailing / )

Nos sistemas GNU, você pode fazer:

find . -delete

Agora, se o diretório atual tiver apenas algumas entradas e a maior parte dos arquivos estiverem em subdiretórios, isso não fará uma diferença significativa e rm -rf -- * provavelmente será o mais rápido possível. É esperado que rm -rf (ou qualquer coisa que remova todos os arquivos) seja caro, pois significa ler o conteúdo de todos os diretórios e chamar unlink() em cada entrada. unlink() em si pode ser muito caro, pois envolve a modificação do inode do arquivo excluído, o diretório que contém o arquivo e algum mapa do sistema de arquivos ou outras áreas que são gratuitas.

rm e find (pelo menos as implementações GNU) já classificam a lista de arquivos pelo número de inode em cada diretório, o que pode fazer uma grande diferença em termos de desempenho em sistemas de arquivos ext4, pois reduz o número de mudanças aos dispositivos de bloco subjacentes quando inodes consecutivos (ou próximos uns dos outros) são modificados em sequência.

rsync ordena os arquivos pelo nome, o que poderia reduzir drasticamente o desempenho, a menos que a ordem por nome coincidisse com a ordem secundária (como quando os arquivos foram criados a partir de uma lista classificada de nomes de arquivos).

Um motivo pelo qual rsync pode ser mais rápido em alguns casos é que ele não parece tomar precauções de segurança para evitar condições de corrida que poderiam fazer com que ele caísse no diretório errado se um diretório fosse substituído por um symlink trabalhando como rm ou find do.

Para otimizar um pouco mais:

Se você souber a profundidade máxima da sua árvore de diretórios, poderá passá-la para find :

find . -maxdepth 3 -delete

Isso economiza find tendo que tentar ler o conteúdo dos diretórios na profundidade 3.

    
por 18.04.2016 / 11:03
7

O mais rápido é com rm -rf dirname . Eu usei um ponto de montagem instantâneo de um sistema de arquivos ext3 no RedHat6.4 com 140520 arquivos e 9699 diretórios. Se rm -rf * for lento, pode ser porque sua entrada de diretório de nível superior tem lotes de arquivos, e o shell está ocupado expandindo * , o que requer um readdir e uma classificação adicionais. Vá até um diretório e faça rm -rf dirname/ .

Method                    Real time    Sys time  Variance (+/-)
find dir -delete          0m8.108s     0m3.668s  0.055s
rm -rf dir                0m7.956s     0m3.640s  0.081s
rsync -delete empty/ dir/ 0m8.305s     0m3.918s  0.029s

Notas:

  • versão do rsync: 3.0.6
  • versão rm / coreutils: 8.4-19
  • find / findutils versão: 4.4.2-6
por 18.04.2016 / 11:32