Wie kann ich unter Linux alle Dateien finden, die einen String enthalten, und sie löschen?

17

Ich möchte alle Dateien löschen, die die Zeichenfolge enthalten foo. Wie kann ich das mit bash unter Linux machen?

Kitsos
quelle
Ist diese Zeichenfolge der Dateiname?
Donnerstag,
3
Bitte klären Sie: Wollen Sie Dateien löschen, deren Namefoo (zB myfoo.jpg) enthält , oder Dateien, die die Bytesequenz enthalten foo(einschließlich Binärdateien, die zufällig diese Bytesequenz enthalten)?
Hammar

Antworten:

33

Hier ist ein sicherer Weg:

grep -lrIZ foo . | xargs -0 rm -f --
  • -l druckt Dateinamen von Dateien, die dem Suchmuster entsprechen.
  • -rführt eine rekursive Suche nach dem Muster fooim angegebenen Verzeichnis durch .. Wenn dies nicht funktioniert, versuchen Sie es -R.
  • -I(groß i) bewirkt, dass Binärdateien wie PDFs übersprungen werden.
  • -Z Stellt sicher, dass Dateinamen mit Nullen (dh mit Nullen) abgeschlossen sind, damit ein Name, der Leerzeichen enthält, nicht falsch interpretiert wird (dh als mehrere Namen anstelle von einem).
  • xargs -0füttert die Dateinamen von grepbis rm -fund trennt die Wörter durch Null (nul) Bytes (merken Sie sich die -ZOption von grep).
  • --wird oft vergessen, aber es ist sehr wichtig, das Ende der Optionen zu markieren und das Entfernen von Dateien zu ermöglichen, deren Namen mit beginnen -.

Wenn Sie sehen möchten, welche Dateien gelöscht werden sollen, entfernen Sie einfach das | xargs -0 rm -f --Teil und lassen Sie die ZOption zu aus grep.

Ein anderer Benutzer schlug Folgendes vor, das Sie nicht ausführen sollten, da es unsicher ist:

files=`grep foo * | cut -d: -f1`
rm -f $files         # unsafe, do not run it!

Wenn ich Dateien habe ImportantStuff, die ich nicht löschen und obsolete ImportantStuffenthalten möchte foo, dann verliere ich ImportantStuff(und nicht obsolete ImportantStuff !), Wenn ich diesen Befehl ausführe, weil $fileser bei der Interpretation an Leerzeichen auseinanderbricht. Es ist gefährlich, auf diese Weise eine Liste von Dateinamen in eine skalare Shell-Variable einzufügen.

Lekensteyn
quelle
17
$ find -type f -exec grep -q "foo" {} \; -exec echo rm -- {} \;

Dies sucht rekursiv nach Dateien mit foo. Die zweite -execwird nur ausgeführt, wenn die erste execerfolgreich beendet wurde, dh wenn grepÜbereinstimmungen vorliegen. Dryrun und entferne das, echowenn die Ausgabe korrekt erscheint.

Oder alternativ

$ find -type f -exec grep -q "foo" {} \; -print

und

$ find -type f -exec grep -q "foo" {} \; -delete

wie von Lekensteyn vorgeschlagen.

Adrian Frühwirth
quelle
4
... was sich verkürzen lässt auf: find -type f -exec grep -q 'foo' {} \; -delete(die Anführungszeichen {}sind überflüssig, können findauch Dateien löschen.) Beachten Sie, dass grepein regulärer Ausdruck akzeptiert wird. Wenn Sie suchen möchten foo.bar, können Sie entweder diese -FOption deaktivieren oder das Muster als Literal behandeln.
Lekensteyn
Irgendein Grund zu benutzen -exec echo rm "{}" \;und nicht -delete?
Vartec
1
@vartec Nein, ich würde verwenden -delete. Es ist nur einfacher, mit der Sekunde -execund dem Echo vor Ort zu demonstrieren .
Adrian Frühwirth
1
Es ist einfacher zu tippen -print(oder -lsfür mehr Ausführlichkeit) als -exec echo rm "{}" \'. Keine Notwendigkeit für externe Dienstprogramme.
Lekensteyn
1
Wenn Sie rm {} verwenden, verwenden Sie rm - {}, damit Sonderzeichen im Dateinamen selbst nicht interpoliert werden.
Tippen
1

Ich würde tun, was Adrian sagt,

Aber ich würde Wortgrenzen hinter dem Foo einfügen, um nicht versehentlich Dateien zu löschen, die "Lebensmittel" enthalten (es sei denn, alles, was Lebensmittel enthält, wird gelöscht, was Sie wollen.)

 $ find -type f -exec grep -q "\<foo\>" {} \; -delete

Eigentlich würde ich die Ausgabe vor dem Löschen umleiten, damit ich sie vor dem Löschen überprüfen kann:

 $ find -type f -exec grep -q "\<foo\>" > /tmp/list_of_files_to_delete
Petter H
quelle
Sobald Sie in der Lage sind, Kommentare zu posten, sollten Sie solche Dinge als Kommentare posten.
FSMaxB
Ja, ich habe es zuerst versucht, aber dann wurde mir klar, dass ich noch keine Kommentare posten darf.
Petter H