it-swarm.com.de

Unix: So löschen Sie in einer Datei aufgelistete Dateien

Ich habe eine lange Textdatei mit einer Liste von Dateimasken, die ich löschen möchte

Beispiel:

/tmp/aaa.jpg
/var/www1/*
/var/www/qwerty.php

Ich muss sie löschen. Versuchte rm `cat 1.txt` und sagt, dass die Liste zu lang ist.

Fand diesen Befehl, aber wenn ich Ordner aus der Liste überprüfe, haben einige von ihnen noch Dateien xargs rm <1.txt Beim manuellen rm-Aufruf werden Dateien aus solchen Ordnern entfernt. Daher gibt es keine Probleme mit Berechtigungen.

68
Alexander

Dies ist nicht sehr effizient, funktioniert aber, wenn Sie Glob-Muster benötigen (wie in/var/www/*). 

for f in $(cat 1.txt) ; do 
  rm "$f"
done

Wenn Sie keine Muster haben und sicher sind, dass Ihre Pfade in der Datei keine Leerzeichen oder andere seltsame Dinge enthalten, können Sie xargs wie folgt verwenden:

xargs rm < 1.txt
89
nos

Angenommen, die Liste der Dateien befindet sich in der Datei 1.txt, dann machen Sie Folgendes:

xargs rm -r <1.txt

Die -r-Option bewirkt eine Rekursion in alle in 1.txt genannten Verzeichnisse.

Wenn Dateien schreibgeschützt sind, erzwingen Sie die Löschung mit der Option -f:

xargs rm -rf <1.txt

Seien Sie vorsichtig bei der Eingabe von any - Werkzeugen, die programmgesteuerte Löschvorgänge ausführen. Stellen Sie sure sicher, dass die in der Eingabedatei genannten Dateien wirklich gelöscht werden sollen. Seien Sie besonders vorsichtig bei scheinbar einfachen Tippfehlern. Wenn Sie beispielsweise ein Leerzeichen zwischen einer Datei und ihrem Suffix eingeben, werden zwei separate Dateinamen angezeigt:

file .txt

ist eigentlich zwei separate Dateien: file und .txt.

Das scheint nicht so gefährlich zu sein, aber wenn der Tippfehler so ist:

myoldfiles *

Dann löschen Sie nicht alle Dateien, die mit myoldfiles beginnen, sondern myoldfiles und all non-dot-Dateien und Verzeichnisse im aktuellen Verzeichnis. Wahrscheinlich nicht, was Sie wollten.

47
aks

xargs -I{} sh -c 'rm {}' < 1.txt sollte tun, was Sie wollen. Seien Sie vorsichtig mit diesem Befehl, da ein falscher Eintrag in dieser Datei zu Problemen führen kann.

Diese Antwort wurde bearbeitet, nachdem @tdavies darauf hingewiesen hatte, dass das Original keine Shell-Erweiterung durchführte.

13
Mark Drago

Benutze das:

while IFS= read -r file ; do rm -- "$file" ; done < delete.list

Wenn Sie eine Glob-Erweiterung benötigen, können Sie die Anführungszeichen $file weglassen:

IFS=""
while read -r file ; do rm -- $file ; done < delete.list

Aber seien Sie gewarnt, dass Dateinamen "problematischen" Inhalt enthalten können, und ich würde die nicht zitierte Version verwenden. Stellen Sie sich dieses Muster in der Datei vor

*
*/*
*/*/*

Dies würde ziemlich viel aus dem aktuellen Verzeichnis löschen! Ich möchte Sie dazu ermutigen, die Löschliste so vorzubereiten, dass Glob-Muster nicht mehr benötigt werden, und dann zitiere wie in meinem ersten Beispiel.

12
hek2mgl

Sie können diesen One-Liner verwenden:

cat 1.txt | xargs echo rm | sh

Welche Shell-Erweiterung führt aber rm so oft wie möglich aus.

11
tgdavies

Sie können '\ n' verwenden, um das neue Zeilenzeichen als Trennzeichen zu definieren.

xargs -d '\n' rm < 1.txt

Seien Sie vorsichtig mit der -rf, da sie das löschen kann, was Sie nicht möchten, wenn der 1.txt Pfade mit Leerzeichen enthält. Deshalb ist das neue Trennzeichen etwas sicherer.

Auf BSD-Systemen können Sie die Option -0 verwenden, um neue Zeilenzeichen als Trennzeichen wie folgt zu verwenden:

xargs -0 rm < 1.txt
11
Ray

cat 1.txt | xargs rm -f | bash Ausführen des Befehls führt nur für Dateien Folgendes aus.

cat 1.txt | xargs rm -rf | bash Der Befehl Ausführen führt das folgende rekursive Verhalten aus.

4
Uzayr

In diesem speziellen Fall würde ich es aufgrund der in anderen Antworten genannten Gefahren tun

  1. Bearbeiten in z. Vim und :%s/\s/\\\0/g, die alle Leerzeichen mit einem Backslash umgehen.

  2. Dann :%s/^/rm -rf /, den Befehl voranstellen. Mit -r brauchen Sie sich keine Sorgen zu machen, dass Verzeichnisse nach den darin enthaltenen Dateien aufgelistet werden, und mit -f wird es nicht wegen fehlender Dateien oder doppelter Einträge beschwert.

  3. Führen Sie alle Befehle aus: $ source 1.txt

2
Evgeni Sergeev

Hier ist ein weiteres Schleifenbeispiel. Diese enthält auch eine 'if-Anweisung', um zu überprüfen, ob es sich bei dem Eintrag um eine 'Datei' handelt (oder um ein 'Verzeichnis'):

for f in $(cat 1.txt); do if [ -f $f ]; then rm $f; fi; done
1
nthparameter

Um eine andere Möglichkeit zu bieten, können Sie auch einfach den folgenden Befehl verwenden

$ cat to_remove
/tmp/file1
/tmp/file2
/tmp/file3
$ rm $( cat to_remove )
0
Quentin

Hier können Sie eine Reihe von Ordnern aus deletelist.txt verwenden, während einige Muster meidet

foreach f (cat deletelist.txt)
    rm -rf ls | egrep -v "needthisfile|*.cpp|*.h"
end
0

Dadurch können Dateinamen Leerzeichen enthalten (reproduzierbares Beispiel).

# Select files of interest, here, only text files for ex.
find -type f -exec file {} \; > findresult.txt
grep ": ASCII text$" findresult.txt > textfiles.txt
# leave only the path to the file removing suffix and prefix
sed -i -e 's/:.*$//' textfiles.txt
sed -i -e 's/\.\///' textfiles.txt

#write a script that deletes the files in textfiles.txt
IFS_backup=$IFS
IFS=$(echo "\n\b")
for f in $(cat textfiles.txt); 
do 
rm "$f"; 
done
IFS=$IFS_backup

# save script as "some.sh" and run: sh some.sh
0
Ferroao