Mir ist klar, dass jede Frage zum Löschen von Dateien mit großer Sorgfalt beantwortet werden muss. Meine erste Antwort war zu voreilig. Ich habe nicht berücksichtigt, dass die Dateiliste fehlerhaft sein kann, um mit egrep verwendet zu werden. Ich habe die Antwort bearbeitet, um dieses Risiko zu verringern.
Das sollte für die Dateien funktionieren, die keinen Platz im Namen haben:
Erstellen Sie zuerst Ihre Dateiliste neu, um sicherzustellen, dass sie mit dem genauen Dateinamen übereinstimmt:
sed -e 's,^,^,' -e 's,$,$,' filelist > newfilelist
Erstellen Sie die rm-Befehle
cd your_directory
ls | egrep -vf newfilelist | xargs -n 1 echo rm > rmscript
Überprüfen Sie, ob das rm-Skript zu Ihnen passt (Sie können es mit "vim" oder "less" tun).
Führen Sie dann die folgende Aktion aus:
sh -x rmscript
Wenn die Dateien Leerzeichen in ihrem Namen haben (wenn die Dateien das Leerzeichen im Namen haben, "
funktioniert dies nicht):
ls | egrep -vf newfilelist | sed 's,^\(.*\)$,rm "\1",' > rmscript
Natürlich sollte sich die Dateiliste nicht im selben Verzeichnis befinden!
EDITIERT:
Die Dateiliste des Nathan enthielt Namen, die mit allen Dateien im Verzeichnis übereinstimmten (wie "html" entspricht "bob.html"). Es wurde also nichts gelöscht, weil egrep -vf
der gesamte Stream absorbiert wurde. Ich habe einen Befehl hinzugefügt, um jedem Dateinamen ein "^" und ein "$" hinzuzufügen. Ich hatte Glück, dass Nathans Dateiliste korrekt war. Wäre es DOS-formatiert mit CR-LF-Endzeilen oder mit zusätzlichen Leerzeichen gewesen, wären vom egrep keine Dateien erhalten und alle gelöscht worden.
ls
liefert die Verzeichnisdateinamen,egrep -vf filelist
filtert Ihre 50 Dateinamen. Ich fürchte, Sie haben alle Ihre Dateien gelöscht.Konstruieren Sie die Argumente vor
find
:Verwenden Sie die
echo
Teile, um zu sehen, was konstruiert werden würde. Entfernen Sie dieecho
Teile, um es tatsächlich auszuführen.Update: Demonstration:
quelle
'
) hinzugefügt werden, dhkeep=( -name \'"$REPLY"\' )
undkeep+=( -o -name \'"$REPLY"\' )
.Mit
zsh
:Es liest die Zeilen
filelist
eines Arrays und verwendet dann glob qualifiers /e
string , um nur die Dateinamen zu globalisieren / auszuwählen, die nicht im Array vorhanden sind: Es werden.
nur reguläre Dateien ausgewählt (hinzufügen,D
wenn Ihre Liste Punktdateien enthält) und das Negierte^e_'expression'_
wählt nur diejenigen für aus wobei der Ausdruck false zurückgibt, dh wenn ihr Name ($REPLY
) kein Element des Arrays ist .Wenn Sie mit dem Ergebnis zufrieden sind, ersetzen Sie es
print -rl
durchrm
, um die Dateien tatsächlich zu entfernen:Verwenden Sie den
*/**
Glob mit${REPLY:t}
Glob-Modifikator, um Dateien rekursiv auszuwählen und zu entfernen :quelle
Wenn Sie den Inhalt des Verzeichnisses wie folgt in eine Datei einfügen:
Offene Dateiliste mit einem Texteditor und entfernen Sie alle Dateien , außer denen , die Sie löschen möchten . Das ist fett gedruckt, weil es der entgegengesetzte Ansatz zur obigen Antwort ist
Versuche dies:
Wenn Ihre Liste der auf dem Bildschirm ausgegebenen Dateien angezeigt wird, ersetzen Sie das Echo durch
rm -v
:quelle
Führen Sie das folgende Skript aus.
all_files
.not_to_be_deleted_files
).not_to_be_deleted_files
undfiles_to_be_deleted
am Ende,not_to_be_deleted_files
wie wir diese 2 Dateien brauchen.join
Befehl gelöscht werden müssen, und leite die Ausgabe in einefiles_to_be_deleted
Datei um.files_to_be_deleted
und entferne die in diesem Dateinamen genannten Dateien.Das Skript ist wie folgt.
PS : Wenn Sie möchten, dass dies als Skript gespeichert und ausgeführt wird, können Sie den Skriptnamen wahrscheinlich auch mit hinzufügen
echo scriptname >> not_to_be_deleted_files
.Obwohl es nicht erforderlich ist, bevorzuge ich es, weil es später kein Bedauern geben wird. Ich habe auf einen kleinen Satz von Dateien getestet und es hat in meinem System funktioniert. Wenn Sie jedoch sicher sein möchten, versuchen Sie es zuerst in einem
test
Verzeichnis und entfernen Sie dann die Dateien im ursprünglichen Verzeichnis.quelle
quelle
Ich habe mich für einen sichereren und viel, viel schnelleren Ansatz entschieden, weil ich 18.000 Dateien in der Liste hatte! Ich musste Bilder in einer großen Drupal-Installation bereinigen.
Das Löschen aller Dateien, die nicht in der Liste enthalten sind, entspricht dem Beibehalten nur der Dateien, die in der Liste enthalten sind. Daher habe ich beschlossen, die Dateien tatsächlich von der Liste an einen anderen Speicherort zu kopieren, aber das Kopieren von 20 GB Dateien würde zu viel Speicherplatz beanspruchen und auch sehr langsam sein. Der Trick besteht also darin, die Dateien
hardlinks
stattdessen mit der-l
Option zu kopierencp
. Dies nimmt fast keinen Platz ein und ist sehr schnell. Da ich die Verzeichnisstruktur beibehalten musste, habe ich außerdem die--parents
Option verwendet.Hier ist ein Auszug aus meiner Dateiliste:
Eine Beispielzeile wäre also, wobei Temp das Ziel ist:
Dadurch wird diese Struktur erstellt:
Beachten Sie, dass sich das Ziel im selben Dateisystem wie die Quelle befinden muss, damit Hardlinks funktionieren.
Der nächste Schritt besteht darin, das Skript zu erstellen:
Angenommen, Sie haben bereits das leere Verzeichnis / some / where / temp erstellt, können Sie die Dateien folgendermaßen kopieren:
Beachten Sie, wie Fehler enden
missing_files
. Der zusätzliche Vorteil dieses Ansatzes besteht darin, dass Sie eine Liste der Dateien aus der ursprünglichen Liste erhalten, die tatsächlich nicht vorhanden sind!Nach dem Ausführen des Skripts enthält temp nur die Dateien, die in der Dateiliste enthalten sind, ohne jedoch etwas zu löschen und ohne zusätzlichen Speicherplatz zu beanspruchen. Wenn Sie mit dem Ergebnis zufrieden sind, können Sie alle Originaldateien einschließlich der Unterordner löschen.
Verschieben Sie abschließend die Dateien und Ordner von temporär an den ursprünglichen Speicherort zurück.
Für die 18.000 Dateien dauerte es nur wenige Sekunden.
quelle
Sicher, einfach.
cd
zum Verzeichnis.Erstellen Sie ein temporäres Verzeichnis.
getan.
quelle