it-swarm.com.de

Löschen Sie effizient ein großes Verzeichnis mit Tausenden von Dateien

Wir haben ein Problem mit einem Ordner, der mit Hunderttausenden winziger Dateien unhandlich wird.

Es gibt so viele Dateien, die rm -rf gibt einen Fehler zurück und stattdessen müssen wir Folgendes tun:

find /path/to/folder -name "filenamestart*" -type f -exec rm -f {} \;

Dies funktioniert, ist jedoch sehr langsam und schlägt ständig fehl, wenn der Speicher knapp wird.

Gibt es einen besseren Weg, dies zu tun? Im Idealfall möchte ich das gesamte Verzeichnis entfernen, ohne mich um den Inhalt zu kümmern.

177
Toby

Die Verwendung von rsync ist überraschend schnell und einfach.

mkdir empty_dir
rsync -a --delete empty_dir/    yourdirectory/

@ Saraths Antwort erwähnte eine weitere schnelle Wahl: Perl! Seine Benchmarks sind schneller als rsync -a --delete.

cd yourdirectory
Perl -e 'for(<*>){((stat)[9]<(unlink))}'

Quellen:

  1. https://stackoverflow.com/questions/1795370/unix-fast-remove-directory-for-cleaning-up-daily-builds
  2. http://www.slashroot.in/which-is-the-fastest-method-to-delete-files-in-linux
238
stevendaniels

Jemand auf Twitter schlug vor, -delete Anstatt von -exec rm -f{} \;

Dies hat die Effizienz des Befehls verbessert, verwendet jedoch immer noch die Rekursion, um alles durchzugehen.

42
Toby

Was ist mit so etwas wie: find /path/to/folder -name "filenamestart*" -type f -print0 | xargs -0rn 20 rm -f

Sie können die Anzahl der gleichzeitig zu löschenden Dateien begrenzen, indem Sie das Argument für den Parameter -n Ändern. Die Dateinamen mit Leerzeichen sind ebenfalls enthalten.

19

Ein kluger Trick:

rsync -a --delete empty/ your_folder/

Es ist super CPU-intensiv, aber sehr, sehr schnell. Siehe https://web.archive.org/web/20130929001850/http://linuxnote.net/jianingy/en/linux/a-fast-way-to-remove-huge-number-of-files .html

16
MZAweb

Ich glaube nicht, dass Sie das tun, was Sie zu tun glauben.

Zuerst habe ich eine große Anzahl von Dateien erstellt, um Ihre Situation zu simulieren:

$ mkdir foo
$ cd foo/
$ for X in $(seq 1 1000);do touch {1..1000}_$X; done

Dann habe ich versucht, was ich erwartet hatte, um zu scheitern, und wie es sich anhört, als würden Sie in der Frage tun:

$ rm -r foo/*
bash: /bin/rm: Argument list too long

Aber das funktioniert funktioniert:

$ rm -r foo/
$ ls foo
ls: cannot access foo: No such file or directory
14
Izkata

Ich hatte die Gelegenheit zu testen -delete verglichen mit -exec rm \{\} \; und für mich -delete war die Antwort auf dieses Problem.

Verwenden von -delete löschte die Dateien in einem Ordner mit 400.000 Dateien mindestens 1.000 Mal schneller als rm.

Der Artikel "So löschen Sie eine große Anzahl von Dateien unter Linux" legt nahe, dass es ungefähr dreimal schneller ist, aber in meinem Test war der Unterschied viel dramatischer.

10
user2365090

Über die -delete Option oben: Ich verwende es, um eine große Anzahl (1M + est) Dateien in einem temporären Ordner zu entfernen, den ich erstellt habe und versehentlich vergessen habe, jede Nacht zu bereinigen. Ich habe meine Festplatte/Partition versehentlich gefüllt, und nichts anderes konnte sie entfernen als das find . Befehl. Es ist langsam, zuerst habe ich verwendet:

find . -ls -exec rm {} \;

Aber das hat EXTREM lange gedauert. Es begann nach ungefähr 15 Minuten, um einige der Dateien zu entfernen, aber ich vermute, dass es weniger als 10 oder so pro Sekunde entfernte, nachdem es endlich gestartet wurde. Also habe ich versucht:

find . -delete

stattdessen und ich lasse es jetzt laufen. Es scheint schneller zu laufen, obwohl es die CPU EXTREM belastet, was der andere Befehl nicht war. Es läuft seit ungefähr einer Stunde und ich glaube, ich bekomme wieder Speicherplatz auf meinem Laufwerk und die Partition "verkleinert sich allmählich", aber es dauert immer noch sehr lange. Ich bezweifle ernsthaft, dass es 1000-mal schneller läuft als das andere. Wie in allen Dingen wollte ich nur auf den Kompromiss zwischen Raum und Zeit hinweisen. Wenn Sie die CPU-Bandbreite zur Verfügung haben (wir tun dies), führen Sie letztere aus. Meine CPU läuft (uptime Berichte):

10:59:17 up 539 days, 21:21,  3 users,  load average: 22.98, 24.10, 22.87

Und ich habe gesehen, dass der durchschnittliche Auslastungsgrad über 30,00 liegt, was für ein ausgelastetes System nicht gut ist, aber für unser System, das normalerweise leicht ausgelastet ist, ist es für ein paar Stunden in Ordnung. Ich habe die meisten anderen Dinge auf dem System überprüft und sie reagieren immer noch, sodass wir vorerst in Ordnung sind.

5
Scotty

Erwägen Sie die Verwendung von Btrfs-Volume und löschen Sie einfach das gesamte Volume für ein solches Verzeichnis mit einer großen Anzahl von Dateien.

Alternativ können Sie eine FS - Bilddatei erstellen, dann die Bereitstellung aufheben und löschen, um alles auf einmal sehr schnell zu entfernen.

4
Sergei

Verwenden rm -rf directory Anstatt von rm -rf *.

Wir machten anfangs rm -rf * im Verzeichnis, um den Inhalt zu löschen und dachte, das sei so schnell wie möglich. Aber dann schlug einer unserer leitenden Ingenieure vor, die Sternchen nicht zu verwenden (*) und übergeben Sie stattdessen das übergeordnete Verzeichnis wie rm -rf directory.

Nach einigen heftigen Debatten darüber, wie dies keinen Unterschied machen würde, beschlossen wir, es zusammen mit einer dritten Methode zur Verwendung von find zu bewerten. Hier sind die Ergebnisse:

time rm -rf *                   2m17.32s
time rm -rf directory           0m15.60s
time find directory -delete     0m16.97s

rm -rf directory ist ungefähr 9 Mal schneller als rm -rf *!

Unnötig zu erwähnen, dass wir diesen Ingenieur ein Bier gekauft haben!

Also verwenden wir jetzt rm -rf directory; mkdir directory, um das Verzeichnis zu löschen und neu zu erstellen.

4
Joshua Pinter

Es gibt einige Methoden, mit denen eine große Anzahl von Dateien unter Linux gelöscht werden kann. Sie können die Option find with delete verwenden, die schneller als die Option exec ist. Dann können Sie Perl Unlink verwenden und dann sogar rsync. So löschen Sie eine große Anzahl von Dateien unter Linux

4
sarath

Unter der Annahme, dass GNU parallel installiert ist, habe ich Folgendes verwendet:

parallel rm -rf dir/{} ::: `ls -f dir/`

und es war schnell genug.

2
Nacho

Das Löschen von WIRKLICH GROSSEN Verzeichnissen erfordert einen anderen Ansatz, wie ich aus dieser Site gelernt habe. Sie müssen ionice verwenden. Es stellt sicher (mit -c3), dass Löschvorgänge nur ausgeführt werden, wenn das System über IO- verfügt. Zeit dafür. Die Systemlast wird nicht zu hoch und alles reagiert weiter (obwohl meine CPU-Suchzeit mit etwa 50% recht hoch war).

find <dir> -type f -exec ionice -c3 rm {} \;
1
gamma

Wenn Sie Millionen von Dateien haben und jede der oben genannten Lösungen Ihr System in Stress versetzt, können Sie diese Inspiration ausprobieren:

Datei Nice_delete:

#!/bin/bash

MAX_LOAD=3
FILES=("[email protected]")
BATCH=100

while [ ${#FILES[@]} -gt 0 ]; do
    DEL=("${FILES[@]:0:$BATCH}")
    ionice -c3 rm "${DEL[@]}"
    echo -n "#"
    FILES=("${FILES[@]:$BATCH}")
    while [[ $(cat /proc/loadavg | awk '{print int($1)}') -gt $MAX_LOAD ]]; do
        echo -n "."
        sleep 1
    done
done

Und jetzt löschen Sie die Dateien:

find /path/to/folder -type f -exec ./Nice_delete {} \+

Suchen erstellt Stapel (siehe getconf ARG_MAX) von einigen Zehntausenden von Dateien und übergeben Sie es an Nice_delete. Dadurch werden noch kleinere Chargen erstellt, um das Schlafen zu ermöglichen, wenn eine Überlastung festgestellt wird.

1
brablc

Abhängig davon, wie gut Sie diese Dateien entfernen müssen, würde ich die Verwendung von shred vorschlagen.

$ shred -zuv folder

wenn Sie das Verzeichnis löschen möchten, es aber nicht entfernen und neu erstellen können, empfehle ich, es zu verschieben und sofort neu zu erstellen.

mv folder folder_del
mkdir folder
rm -rf folder_del

das ist schneller, ob Sie es glauben oder nicht, da nur eine Inode geändert werden muss. Denken Sie daran: Sie können diesen Geschmack auf einem Multicore-Computer nicht wirklich parallelisieren. Es kommt auf den Festplattenzugriff an, der durch das RAID oder was Sie haben begrenzt ist.

0
polemon

Python-Skripte sollten nicht als unrein gemieden werden:

#!/usr/bin/python3

import shutil
path_for_deletion = input( 'path of dir for deletion> ' ) 
print( 'about to remove ' + path_for_deletion + ' ...' )
shutil.rmtree( path_for_deletion, ignore_errors=True )
print( '... done' )

Ich habe den Mann, der ein nützliches Benchmarking verschiedener Methoden durchgeführt hat hier gefragt, ob er versuchen könnte, dies zu vergleichen. Aus meinen Experimenten scheint es ziemlich gut zu sein.

NB Fehler könnten behandelt werden, um sie zumindest auszudrucken ... aber es könnte einfacher sein, danach trash myDirectoryForDeletion Oder rm -rfv myDirectoryForDeletion Auszuführen.

0
mike rodent

Wenn Sie nur so schnell wie möglich viele Dateien entfernen möchten ls -f1 /path/to/folder/with/many/files/ | xargs rm funktioniert möglicherweise einwandfrei, aber führen Sie es besser nicht auf Produktionssystemen aus, da Ihr System möglicherweise IO Probleme und Anwendungen können während des Löschvorgangs hängen bleiben).

Dieses Skript funktioniert gut für viele Dateien und sollte die ioload des Systems nicht beeinflussen.

#!/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
0
Leon Kramer

Für Izkatas obigen Hinweis:

Aber das funktioniert :

$ rm -r foo/
$ ls foo
ls: cannot access foo: No such file or directory

Das hat fast funktioniert - oder hätte funktioniert -, aber ich hatte einige Probleme mit der Erlaubnis; Dateien befanden sich auf einem Server, aber ich verstehe immer noch nicht, woher dieses Berechtigungsproblem kam. Wie auch immer, Terminal bat um Bestätigung für jede Datei. Die Anzahl der Dateien betrug ungefähr 20 000, daher war dies keine Option. Nach "-r" habe ich die Option "-f" hinzugefügt, daher war der gesamte Befehl "rm -r -f Ordnername / = ". Dann schien es gut zu funktionieren. Ich bin ein Neuling bei Terminal, aber ich denke, das war okay, oder? Vielen Dank!

0
user41527
ls -1 | xargs rm -rf 

sollte im Hauptordner funktionieren

0
PsyStyle

Verwenden Sie ls -f | xargs -n 5000 rm, Während Sie den -n Für die Stapelgröße an Ihr System anpassen (ein großes Lob an @digital_infinity für den Tipp -n).

Zusätzlich können Sie die Auflistung mit einem Inline-Grep filtern, z. ls -f | grep '^156' | xargs -n 5000 rm.

Nach meiner Erfahrung ist dies weitaus schneller als Techniken, die find verwenden, und macht komplexere Shell-Skripte überflüssig.

0
buckaroo1177125