Wie entferne ich alle Dateien, die einen bestimmten Text nicht enthalten?
Ich verstehe die Lösung zum Entfernen von Dateien mit einem angegebenen Text, aber ich muss Dateien entfernen, die KEIN angegebenes Muster enthalten.
Der folgende Befehl erstellt eine Liste von Dateien, die „successful run“ nicht enthalten:
grep -c "successful run" *.out | grep -v ":1" > err.txt
Ich möchte diese Dateien direkt löschen.
Antwort1
Ihr ursprünglicher Ansatz zur Identifizierung geeigneter Dateien
grep -c "successful run" *.out | grep -v ":1"
ist fehlerhaft. Hauptbedenken:
- Was passiert, wenn in einer Datei zwei oder mehr übereinstimmende Zeilen vorhanden sind?
grep ":0"
scheint besser auf die Bedingung im Titel Ihrer Frage zu passen („Dateien, die kein Muster enthalten“). - Was ist, wenn
:1
(oder:0
) im Dateinamen vorkommt? Dasgrep ':0$'
scheint sogar noch besser zu sein. - Was passiert, wenn in einem der vom ersten übergebenen Dateinamen ein Zeilenumbruchzeichen vorhanden ist
grep
?
Ich sage, verlassen Sie sich nicht auf grep -c
; verlassen Sie sich auf den Beendigungsstatus, grep
der vorliegt, 1
wenn keine Zeilen ausgewählt wurden.
for f in *.out; do
[ -f "$f" ] && {
grep -q -- "successful run" "$f"
[ "$?" -eq 1 ] && rm -i -- "$f"
}
done
Anmerkungen:
[ -f "$f" ] && …
lässt nichtgrep
die Arbeit mit passenden Verzeichnissen, FIFOs usw. zu*.out
; nur mit regulären Dateien.- Die Bedeutung und Wichtigkeit von
--
wird erklärtHier. Wenn eine Datei mit einem Namen vorhanden ist, der mit beginnt-
, kann sie für eine Option gehalten werden. Eine andere Möglichkeit, mit diesem Problem umzugehen, ist . Auf diese Weise beginntfor f in ./*.out; do …
jede Erweiterung mit und kann nicht mit beginnen .$f
./
-
- Ich habe
rm -i
nur für alle Fälle verwendet. Nachdem Sie die Lösung getestet haben, möchten Sie es vielleicht weglassen-i
. grep … || rm …
ist schlimmer. Wenn ein echter Fehler auftritt (z. B. Zugriff verweigert), ist der Exit-Statusgrep
größer als1
; dann möchten Sie die Datei wahrscheinlich nicht entfernen. Meine Lösung prüft, ob der Exit-Status genau ist1
.- Ihr Originalcode wandert nicht in Unterverzeichnisse, meiner auch nicht. Wenn Sie Rekursion wünschen, ist eine Shell, die dies unterstützt (z. B. Bash mit
shopt -s globstar
und**
), oder eine auf basierende Lösungfind
nützlich.
Antwort2
Wenn Sie davon ausgehen, dass Ihre Dateien entweder einen einzigen „erfolgreichen Lauf“ aufweisen oder keinen, gilt Folgendes:
Um die passenden Dateien zu finden, können Sie Folgendes tun:
grep -l "successful run" *.out > err.txt
um sie zu finden und zu entfernen:
grep -l "successful run" *.out | xargs rm
Um die Dateien ohne Übereinstimmung zu finden, gehen Sie folgendermaßen vor:
grep -vl "successful run" *.out > ok.txt
um sie zu finden und zu entfernen:
grep -vl "successful run" *.out | xargs rm
Die Flaggen bedeuten:
-l lists the files with matches
-v/--invert-match inverts the matching logic