Uma maneira mais rápida de excluir um grande número de arquivos [duplicados]

11

Eu tenho um diretório onde muitos arquivos em cache são gerados muito rapidamente. Como esses arquivos são muito pequenos, está consumindo todos os meus inodes muito rapidamente.

Atualmente, estou executando o seguinte comando para encontrar todos os arquivos com mais de 12 horas e excluí-los.

$ find ./cache -mtime +0.5 -exec rm {} \;

Mas a taxa na qual esse comando está excluindo é mais lenta do que a taxa na qual os arquivos estão sendo gerados. Alguém pode me dizer alguma maneira alternativa para remover um grande número de arquivos rapidamente.

    
por pradeepchhetri 21.10.2013 / 10:48

8 respostas

16

Tente usar xargs :

find ./cache -mtime +0.5 -print0 | xargs -0 rm -f

Atualizar explicação para @pradeepchhetri

Se você usar find com -exec , todos os arquivos que find encontrar chamarão rm uma vez. Então, se você encontrou um grande número de arquivos, ou seja, 10.000 arquivos, você chamou rm 10000 vezes.

xargs tratará a saída de find como argumento de comando para rm , para que xargs forneça tantos argumentos quanto rm possa manipular de uma só vez, ou seja, rm -f file1 file2 ... fazer o programa correr mais rápido.

    
por 21.10.2013 / 11:00
22

find … -exec rm {} \; executa o comando rm para cada arquivo. Mesmo que iniciar um novo processo seja muito rápido, ainda é muito mais lento do que o simples ato de excluir um arquivo.

find … -exec rm {} + chamaria rm em lotes, o que é muito mais rápido: você paga o custo de executar rm uma vez por lote e cada lote executa muitas exclusões.

Ainda mais rápido é não invocar rm . O comando find no Linux possui uma ação -delete para excluir um arquivo correspondente.

find ./cache -mtime +0.5 -delete

No entanto, se você está produzindo arquivos com uma taxa que find … -exec rm {} \; não pode acompanhar, provavelmente há algo errado com sua configuração. Se cache contiver milhões de arquivos, você deverá dividi-lo em subdiretórios para acesso mais rápido.

    
por 21.10.2013 / 18:00
2

se a taxa de criação exceder a taxa de exclusão de que você é o melhor, deixando o cache completamente vazio e removendo arquivos antigos sem nenhuma avaliação do mtime

mv cache foobar
mkdir cache
# may require app restart
rm -rf foobar
    
por 21.10.2013 / 23:34
1

Embora o find seja a melhor abordagem (mais simples, idiomática),

find $dir -exec rm {} +

Você pode mover o diretório para o lado, criar um novo diretório (para o seu programa) e excluir ...

mv $idr old$dir && mkdir $dir && rm -rf old$dir

mas talvez o seu problema seja criar muitos arquivos. Por que não alterar seu programa para anexar a um arquivo existente, em vez de criar um novo arquivo? E então você poderia mover isso (arquivo de log) de lado, e então seu programa poderia criar / anexar um novo arquivo, por exemplo,

fd = open("logfile","a+");
    
por 21.10.2013 / 21:59
1

Se você quiser apenas se livrar de muitos arquivos o mais rápido possível ls -f1 /path/to/folder/with/many/files/ | xargs rm pode funcionar bem, mas é melhor não executá-lo em sistemas de produção porque seu sistema pode se tornar IO e os aplicativos podem ficar travados durante a operação de exclusão .

Este script funciona muito bem para muitos arquivos e não deve afetar o ioload do sistema.

#!/bin/bash

# Path to folder with many files
FOLDER="/path/to/folder/with/many/files"

# Temporary file to store file names
FILE_FILENAMES="/tmp/filenames"

if [ -z "$FOLDER" ]; then
    echo "Prevented you from deleting everything! Correct your FOLDER variable!"
    exit 1
fi

while true; do
    FILES=$(ls -f1 $FOLDER | wc -l)
    if [ "$FILES" -gt 10000 ]; then
        printf "[%s] %s files found. going on with removing\n" "$(date)" "$FILES"
        # Create new list of files
        ls -f1 $FOLDER | head -n 5002 | tail -n 5000 > "$FILE_FILENAMES"

        if [ -s $FILE_FILENAMES ]; then
            while read FILE; do
                rm "$FOLDER/$FILE"
                sleep 0.005
            done < "$FILE_FILENAMES"
        fi
    else
        printf "[%s] script has finished, almost all files have been deleted" "$(date)"
        break
    fi
    sleep 5
done
    
por 23.06.2015 / 20:28
0

rm -rf directory / também funciona mais rápido para bilhões de arquivos em uma pasta. Eu tentei isso.

    
por 17.04.2014 / 03:02
0

Outra solução específica para Linux seria usar as instalações inotify (7) ; você detectará quando os arquivos forem adicionados e, em seguida, executará imediatamente algo para remover os mais antigos.

OTOH, acho que você pode ter algum problema XY . Por que você tem tantos arquivos novos? Talvez usando sqlite, ou arquivos indexados GDBM, ou algum banco de dados real (por exemplo, PostGresQL, MariaDB, MongoDB) pode ser melhor .... Talvez você precise de algum sistema de controle de versão como git ?

    
por 16.07.2015 / 14:01
-2
find . -name -mtime +0.5 -print -delete 

é outra opção para excluir rapidamente um grande número de arquivos.

    
por 25.11.2014 / 07:33

Tags