Wie lösche ich mehrere Dateien gleichzeitig in Bash unter Linux?

103

Ich habe diese Liste von Dateien auf einem Linux-Server:

abc.log.2012-03-14
abc.log.2012-03-27
abc.log.2012-03-28
abc.log.2012-03-29
abc.log.2012-03-30
abc.log.2012-04-02
abc.log.2012-04-04
abc.log.2012-04-05
abc.log.2012-04-09
abc.log.2012-04-10

Ich habe ausgewählte Protokolldateien nacheinander mit dem folgenden Befehl gelöscht rm -rf:

rm -rf abc.log.2012-03-14
rm -rf abc.log.2012-03-27
rm -rf abc.log.2012-03-28

Gibt es eine andere Möglichkeit, um die ausgewählten Dateien sofort zu löschen?

user1253847
quelle
4
Und "Sag GNU / Linux, nicht nur Linux", ich höre jemanden von den Rücksitzen donnern.
Boris Stitnicky
8
Übrigens, warum die -rf? Sind das Ordner? f ist zu erzwingen, r ist für rekursiv. Es funktioniert, wenn es sich nur um eine Datei handelt, aber Sie sollten gewarnt sein. Die Verwendung von -rf jedes Mal, wenn Sie etwas löschen möchten, ist sehr (sehr) (sehr, sehr) gefährlich. (und Sie sollten das Tag "bash" hinzufügen, weil "Linux" zu breit ist.
Depado
@ BorisStitnicky - Ich bin gespannt, warum das GNUbenötigt wird?
user66001
2
@ user66001: Für die Meinung des GNU-Projekts zu diesem Thema: gnu.org/gnu/linux-and-gnu.html . Ich nehme zu dieser Angelegenheit keine Position ein, zumindest nicht hier, und dies ist nicht der Ort, um darüber zu debattieren.
Keith Thompson
2
@ BorisStitnicky - Keine Notwendigkeit zu debattieren, war völlig ahnungslos, und dieser Link gab mir die Informationsstufe, die ich suchte +1
user66001

Antworten:

159

Bash unterstützt alle Arten von Platzhaltern und Erweiterungen.

Ihr genauer Fall würde durch Klammererweiterung wie folgt behandelt:

$ rm -rf abc.log.2012-03-{14,27,28}

Das Obige würde sich zu einem einzigen Befehl mit allen drei Argumenten erweitern und der Eingabe entsprechen:

$ rm -rf abc.log.2012-03-14 abc.log.2012-03-27 abc.log.2012-03-28

Es ist wichtig zu beachten, dass diese Erweiterung von der Shell durchgeführt wird, bevor sie rmüberhaupt geladen wird.

entspannen
quelle
Verwenden Sie nicht "rm", wenn Sie die Dateien in Zukunft wiederherstellen möchten. Sie können das Dienstprogramm "rm-trash" verwenden: github.com/nateshmbhat/rm-trash
Natesh bhat
75

Verwenden Sie einen Platzhalter ( *), um mehrere Dateien abzugleichen.

Mit dem folgenden Befehl werden beispielsweise alle Dateien gelöscht, deren Namen mit beginnen abc.log.2012-03- .

rm -f abc.log.2012-03-*

Ich würde empfehlen zu laufen ls abc.log.2012-03-* , die Dateien auszuführen, damit Sie sehen können, was Sie löschen möchten, bevor Sie den rmBefehl ausführen.

Weitere Informationen finden Sie in der Bash-Manpage zur Dateinamenerweiterung .

Dogbane
quelle
Sehr nützlich, aber es wird nicht um Bestätigung zum Löschen gebeten. Bitte beachten Sie.
Nuriselcuk
1
@nuriselcuk Sie können -i hinzufügen, um eine Bestätigung für jede zu löschende Datei zu erhalten.
Felipe Romero
Funktionierte wie ein Zauber auf AWS Ec2-Instance unter Amazon Linux 1 :) Vielen Dank.
Kyle Bridenstine
41

Wenn Sie alle Dateien löschen möchten, deren Namen einem bestimmten Formular entsprechen, ist ein Platzhalter (Glob-Muster) die einfachste Lösung. Einige Beispiele:

$ rm -f abc.log.*             # Remove them all
$ rm -f abc.log.2012*         # Remove all logs from 2012
$ rm -f abc.log.2012-0[123]*  # Remove all files from the first quarter of 2012

Reguläre Ausdrücke sind leistungsfähiger als Platzhalter. Sie können die Ausgabe von grepbis füttern rm -f. Wenn beispielsweise einige der Dateinamen mit "abc.log"und andere mit beginnen "ABC.log", grepkönnen Sie eine Übereinstimmung ohne Berücksichtigung der Groß- und Kleinschreibung durchführen:

$ rm -f $(ls | grep -i '^abc\.log\.')

Dies führt zu Problemen, wenn einer der Dateinamen lustige Zeichen enthält, einschließlich Leerzeichen. Achtung.

Wenn ich dies tue, führe ich zuerst den ls | grep ...Befehl aus und überprüfe, ob er die gewünschte Ausgabe erzeugt - insbesondere wenn ich Folgendes verwende rm -f:

$ ls | grep -i '^abc\.log\.'
(check that the list is correct)
$ rm -f $(!!)

Dabei wird !!auf den vorherigen Befehl erweitert. Oder ich kann Aufwärtspfeil oder Strg-P ​​eingeben und die vorherige Zeile bearbeiten, um die hinzuzufügenrm -f Befehl .

Dies setzt voraus, dass Sie die Bash-Shell verwenden. Einige andere Shells, insbesondere csh und tcsh sowie einige ältere, von sh abgeleitete Shells, unterstützen die $(...)Syntax möglicherweise nicht . Sie können die entsprechende Backtick-Syntax verwenden:

$ rm -f `ls | grep -i '^abc\.log\.'`

Das $(...) Syntax ist einfacher zu lesen und wenn Sie wirklich ehrgeizig sind, kann sie verschachtelt werden.

Wenn die Teilmenge der Dateien, die Sie löschen möchten, nicht einfach mit einem regulären Ausdruck ausgedrückt werden kann, besteht ein Trick, den ich häufig verwende, darin, die Dateien in einer temporären Textdatei aufzulisten und sie dann zu bearbeiten:

$ ls > list
$ vi list   # Use your favorite text editor

Ich kann die listDatei dann manuell bearbeiten , wobei nur die Dateien übrig bleiben, die ich entfernen möchte, und dann:

$ rm -f $(<list)

oder

$ rm -f `cat list`

(Dies setzt wiederum voraus, dass keiner der Dateinamen lustige Zeichen enthält, insbesondere Leerzeichen.)

Oder wenn listich die Datei bearbeite , kann ich rm -f am Anfang jeder Zeile Folgendes hinzufügen und dann:

$ . ./list

oder

$ source ./list

Bearbeiten der Datei ist auch eine Gelegenheit zitiert , wo nötig hinzuzufügen, zum Beispiel Wechsel rm -f foo barzu rm -f 'foo bar'.

Keith Thompson
quelle
8

Verwenden Sie einfach die mehrzeilige Auswahl in sublime, um alle Dateien in einer einzigen Zeile zu kombinieren, ein Leerzeichen zwischen den einzelnen Dateinamen einzufügen und rmam Anfang der Liste einzufügen. Dies ist vor allem dann nützlich, wenn die zu löschenden Dateinamen kein Muster enthalten.

[$]> rm abc.log.2012-03-14 abc.log.2012-03-27 abc.log.2012-03-28 abc.log.2012-03-29 abc.log.2012-03-30 abc.log.2012-04-02 abc.log.2012-04-04 abc.log.2012-04-05 abc.log.2012-04-09 abc.log.2012-04-10
Andy
quelle
Dies sollte die akzeptierte Antwort sein, da sie die gestellte Frage explizit beantwortet. Es ist freundlicher für Leute, die von Google hierher gekommen sind.
ATLief
5

Ein Platzhalter würde hierfür gut funktionieren, obwohl es aus Sicherheitsgründen am besten ist, die Verwendung des Platzhalters so gering wie möglich zu halten, also etwas in dieser Richtung:

rm -rf abc.log.2012-*

Obwohl es so aussieht, sind das nur einzelne Dateien? Die rekursive Option sollte nicht erforderlich sein, wenn keines dieser Elemente Verzeichnisse sind. Verwenden Sie dies daher am besten nicht, nur aus Sicherheitsgründen.

lacrosse1991
quelle
2

Ich bin kein Linux-Guru, aber ich glaube, Sie möchten Ihre Liste der Ausgabedateien an weiterleiten xargs rm -rf. Ich habe so etwas in der Vergangenheit mit guten Ergebnissen verwendet. Testen Sie zuerst ein Beispielverzeichnis!

BEARBEITEN - Ich habe es möglicherweise falsch verstanden, basierend auf den anderen Antworten, die angezeigt werden. Wenn Sie Platzhalter verwenden können, großartig. Ich nahm an, dass Ihre ursprüngliche Liste, die Sie angezeigt haben, von einem Programm generiert wurde, um Ihnen Ihre "Auswahl" zu geben, und dachte daher, Piping to xargswäre der richtige Weg.

Dave
quelle
-1

Wenn Sie alle Dateien, die zu einem Verzeichnis gehören, gleichzeitig löschen möchten. Beispiel: Ihr Verzeichnisname lautet "log" und das Verzeichnis "log" enthält die Dateien abc.log.2012-03-14, abc.log.2012-03-15 usw. Sie müssen sich über dem Protokollverzeichnis befinden und:

rm -rf /log/*
Alican
quelle