Wie lösche ich alle Dateien in einem Verzeichnis mit Ausnahme einiger?


123

Ich muss alle Dateien in einem Verzeichnis löschen, aber einige davon ausschließen. Zum Beispiel muss a b c ... zich in einem Verzeichnis mit den Dateien alle außer uund löschen p. Gibt es eine einfache Möglichkeit, dies zu tun?


Die folgenden Antworten sind viel besser, aber Sie können die Dateien nur schreibgeschützt speichern, alle löschen und sie dann wieder auf ihre ursprünglichen Berechtigungen zurücksetzen (solange Sie rm -f nicht verwenden). Sie müssen wissen, welche Berechtigungen wiederhergestellt werden müssen, und Sie müssen wissen, dass während des Vorgangs kein Schreibzugriff erforderlich ist. Deshalb sind die anderen Antworten besser.
Joe

1
Wenn Sie auch versteckte Dateien löschen möchten, führen Sie diese shopt -s dotglobvor dem Ausführen aus rm (...).

Antworten:


108

Was ich in diesen Fällen tue, ist zu tippen

rm *

Dann drücke ich Ctrl+ X, erweitern in allen sichtbaren Dateinamen.* *

Dann kann ich einfach die beiden Dateien, die ich behalten möchte, aus der Liste entfernen und schließlich die Befehlszeile ausführen.


25
Ich denke, das funktioniert nur, solange die Liste der Dateien, die auch *erweitert wird, nicht zu lang wird. : -}
Frerich Raabe

9
Esc gefolgt von * erweitert auch das "*".
Slowpoison

2
@ SantoshKumar: Das ergibt für mich keinen Sinn. Die Erweiterung funktioniert immer, es hängt nicht davon ab, welchen Befehl Sie danach verwenden möchten.
Der Hochstapler

2
@OliverSalzburg Die Kombination ist leider etwas verwirrend. Ich denke, du solltest schreiben wie Ctrl+ Shift+ x+*
Santosh Kumar

2
@ SantoshKumar: Aber das ist nicht die Kombination.
Der Hochstapler

143

Für rmalle außer u,pin bash geben Sie einfach ein:

rm !(u|p)

Dazu muss die folgende Option festgelegt werden:

shopt -s extglob

Weitere Infos : glob - Gregs Wiki


1
Sie haben müssen 'extglobbing' aktiv: shopt es extglob
sparkie

18
Sie müssen shopt -s extglob@Ashot. Außerdem sind es nur Dateien, keine Verzeichnisse, weshalb ich die -rfOptionen in Ihrem Befehl entfernt habe.
Slhck

4
Wenn Sie eine Datei ausschließen müssen aus einer Auswahl von Dateien, versuchen Sie dies: rm !(index).html. Dadurch werden alle Dateien mit der Endung ".html" mit Ausnahme von "index.html" gelöscht.
mzuther

71

Sie können verwenden find

find . ! -name u ! -name p -maxdepth 1 -type f -delete
  • ! negiert den nächsten Ausdruck
  • -name Gibt einen Dateinamen an
  • -maxdepth 1Der Suchvorgang wird nur für das angegebene Verzeichnis ausgeführt ( findstandardmäßig werden Verzeichnisse durchsucht).
  • -type f verarbeitet nur Dateien (und nicht zum Beispiel Verzeichnisse)
  • -delete löscht die Dateien

Sie können dann die Bedingungen in der Manpage von find anpassen

Aktualisieren

  • Beachten Sie, dass die Reihenfolge der Elemente der Ausdrücke wichtig ist (siehe Dokumentation).
  • Testen Sie Ihren Befehl zuerst unter Verwendung -printanstelle von-delete

    find . ! -name u ! -name p -maxdepth 1 -type f -print

5
Die Reihenfolge der Prädikate ist hier entscheidend. Wenn man es -deletekurz danach legt ., wird es eine Katastrophe sein (löscht alle Dateien in CWD)
Michał Šrajer

Dies könnte kompakter geschrieben werden alsfind . -maxdepth 1 -type f -name '[^up]' -delete
Kojiro

4
@kojiro ja aber nur für dateien die nur ein buchstabe sind. Bei komplexeren Namen könnte der reguläre Ausdruck ein Chaos sein.
Matteo

2
findist mein bester Freund, vor allem, wenn es zu viele Dateien zu glob
Terence Johnson

43

Einfach:

mvdie gewünschten dateien in einem oberen verzeichnis, rmdas verzeichnis und dann mvwieder zurück.


13
Natürlich mv sie in ein höheres Verzeichnis. Versuchen Sie, sie nicht in ein zu
löschendes

@Konerak: rmwithout entfernt -rkeine Unterverzeichnisse.
Reinierpost

11
Dadurch werden gleichnamige Dateien
Matteo

7
Ich stimme dem nicht zu, weil es zwar praktisch sein kann, aber nicht atomar ist und alle Dateien in kurzer Zeit effektiv aus dem Verzeichnis entfernt. Dies ist nicht akzeptabel, wenn beispielsweise die Dateien im Netzwerk freigegeben werden.
Sam Hocevar

15

Etwas ähnlich zu dieser Antwort, aber keine besonderen Optionen erforderlich, soweit ich weiß, wird die folgende "alte" Funktionalität von einer (vagen) / bin / sh-ähnlichen Shell (z. B. bash, zsh, ksh usw.) unterstützt.

rm [^up]

2
Dies funktioniert für die 1-Zeichen-Dateinamen. Bei längeren Namen ist die Antwort von sparkie besser.
Glenn Jackman

3
Was wäre falsch daran rm [^up]*? Ich mache ziemlich oft ähnliche Dinge.
einen Lebenslauf vom

3
@ MichaelKjörling - Damit werden alle Dateien gelöscht, die mit u oder p beginnen, nicht nur die mit den Namen u und p. Ich denke, das OP (@Ashot) bedeutete das az und u, p, etc. symbolisch und nicht wörtlich.
Sudipta Chatterjee

4
@HobbesofCalvin Das würde alle Dateien löschen, die nicht mit u oder p beginnen, nicht die, die mit ihnen beginnen.
rjmunro

@rjmunro - danke, habe das verpasst! :)
Sudipta Chatterjee

11

Tun ohne zu finden:

ls | grep -v '(u|p)' | xargs rm

(Bearbeiten: "u" und "v" werden, wie an anderen Stellen hier, als generische Versionen ganzer regulärer Ausdrücke verwendet. Natürlich sollten Sie darauf achten, Ihre regulären Ausdrücke zu verankern, um zu viele Übereinstimmungen zu vermeiden.)

Sie werden definitiv ein Drehbuch wollen, wenn Sie viel davon tun wollen, wie andere vorgeschlagen haben.


grep verarbeitet standardmäßig keine erweiterten regulären Ausdrücke: entweder use -Eoderegrep
Matteo

2
Dies schließt alle Dateien aus, die a uoder a enthalten.p
Matteo

@ Matteo Nein, wird es nicht. Das grep grept nicht die Dateien, sondern die Ausgabe des ls-Befehls. Sie denken an etwas, grep -L (u|p)' * | xargs rmbei dem es sich um -Leine Liste von Dateinamen handelt, die keine Übereinstimmung enthalten.
rjmunro

4
Oh, du meinst jede Datei, deren Name uoder enthält p, keine Datei, die a uoder a enthält p. Das ist richtig. Sie können das egrep -v '^(u|p)$'
Problem

1
Hier wird alles außer diesen Übereinstimmungen entfernt! ls | grep -v 'vuze\|progs' | xargs rm -rf
Nick

6

In zsh:

setopt extended_glob  # probably in your .zshrc

dann

rm ^(u|p)

oder

rm *~(u|p)

Die zweite funktioniert sogar , wenn Sie ^in $histcharsfür Geschichte Substitution, und natürlich können Sie einen beliebigen glob vor dem setzen ~.


5

GLOBIGNORE führt eine durch Doppelpunkte getrennte Liste

GLOBIGNORE=u:p
rm *

12
Dies funktioniert auf meiner Shell nicht (GNU Bash 4.1.5 (1)). Stellen Sie sicher, dass Sie es zuerst mit etwas testen, das weniger schädlich ist alsrm oder in einem Testverzeichnis!
einen Lebenslauf vom

3

In der Floppy-Ära hatte ich eine ausführbare Datei namens "Except", die Dinge temporär aus dem aktuellen Verzeichnis verschob und einen Befehl ausführte, also könnte man sagen:

außer * .txt del *. *

um alles außer Ihren Textdateien zu löschen.

Dies wäre eine ziemlich triviale Sache, um sie als Shell-Skript zu implementieren, und wenn dies die Art von Sache ist, die Sie wahrscheinlich mehr als zweimal ausführen, scheint es, als wäre es eine gute Idee.


2
Es erinnerte mich an dasselbe. Im Zeitalter des Multitasking ist ein vorübergehendes Herausziehen aus dem Ordner möglicherweise keine gute Idee :)
Sedat Kapanoglu

3
 find . -maxdepth 1 ! -name "u" ! -name "p" -type f -exec rm -rf {} \;

Dadurch werden alle Dateien mit Ausnahme von u und p in Unix gelöscht


2

Für diejenigen, die es vorziehen, beliebige komplexe Ausschlussmuster (die sich über alle betroffenen Dateinamen erstrecken) in einem ausgewachsenen Regexp-Emacs-, Posix-awk- oder Posix-Extended-Stil anzugeben (siehe Manpage finden), würde ich dieses empfehlen. Ausgeschlossen ist uund pin aktuellem Verzeichnis in diesem Beispiel. Dies kann für Skripte nützlich sein.

find -regextype posix-awk ! -regex './(u|p)' -print0 | xargs -0 rm -rf

Sie müssen vor dem Ausdruck ein Verzeichnis angeben (`find. -Regextype ...).
Matteo

-regextypefunktioniert nur auf GNU-Versionen
Matteo

no - meine find-version (debian squeeze) benötigt definitiv kein explizites verzeichnis vor dem ausdruck, wenn das aktuelle verzeichnis verwendet werden soll
sparkie

@sparke: Dies funktioniert nur bei GNU-Implementierungen
Matteo

@sparkie: Das nicht definierte Verzeichnis (erster Parameter) findist eine GNU-Erweiterung des findBefehls. Gleiches gilt für die -regextypeOption. Außerdem löscht Ihr Befehl auch Dateien in Unterverzeichnissen, während die ursprüngliche Frage eindeutig nach Dateien in einem Verzeichnis gestellt wird.
Mikko Rantalainen

1

Ich benutze immer:

rm [a-o,q-t,v-z]*

Auf diese Weise können Sie definieren, wie detailliert Sie es machen möchten. Wenn Sie also eine bis-zu-Z-Datei löschen möchten, können Sie Folgendes verwenden:

rm [a-o,z]*

1

Noch eine andere Version mit xargs:

ls -1 | grep -v do_not_delete | xargs -I files rm "files"

Beachten Sie, dass dies xargs -Ierforderlich ist, um Dateinamen einschließlich Leerzeichen korrekt zu behandeln.


1

Noch ein anderer:

for FILE in ./*; do if [[ $FILE != ./u* ]] || [[ $FILE != ./p* ]];then rm $FILE; fi; done;

Es ist etwas langwierig und ich weiß nicht, ob Sie es leicht in eine Funktion umwandeln können, die leicht eine beliebige Anzahl von Argumenten aufnehmen kann, aber es funktioniert gut.

Und es ist pure Bash-Güte.


1

Hier ist eine andere Variante. Du kannst Tippen:

rm -i *

oder:

rm --interactive *

So rmwerden Sie aufgefordert, das Löschen jeder Datei zu bestätigen.


1

Verwenden:

find . -type f ! -name 'u' ! -name 'p' ! -name '*.ext' -delete
find . -type d ! -name 'u' ! -name 'p' ! -name '*.ext' -delete

um alle Dateien einschließlich der Verzeichnisse mit Ausnahme von u-, p- und .ext-Dateien zu löschen.


0

Eine einfache Methode, die nur schwer durcheinander zu bringen ist: Nehmen wir an, Sie möchten alles außer * .pdf löschen:

mkdir tmp
mv *.pdf tmp
rm *
mv tmp/* .
rm -r tmp
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.