Vor kurzem stand ich vor der Aufgabe, alle Dateien / Ordner in einem Verzeichnis zu löschen, mit Ausnahme derjenigen, die einem bestimmten Muster entsprechen. Also habe ich mir einen einzeiligen Unix-Befehl ausgedacht, um die Arbeit zu erledigen. Muss es nur eine Zeile sein? Ich nehme nicht an, aber so ist es definitiv cooler!
Obwohl das Problem ziemlich einfach ist, war ich ein wenig überrascht, wie komplex meine Lösung war. Hier ist der Befehl, den ich verwendet habe; HINWEIS: Dies ist eine schlechte Lösung, da keine Dateinamen mit Zeilenvorschubzeichen verarbeitet werden (was in meiner Situation keine Rolle spielte).
ls | grep -v PATTERN | xargs -n1 -IREPLACE rm -rf REPLACE
Ich habe den Befehl "find" nicht verwendet, da ich nicht in Ordner zurückkehren möchte, die mit PATTERN übereinstimmen. Betrachten Sie beispielsweise die folgende Dateistruktur:
file_foo.txt
first_dir
|
+--> contents
+--> ...
foo_dir
|
+--> anotherfile.txt
+--> morefiles.log
foo_file.txt
somefile.txt
Bei Verwendung des Musters "foo" dürfen nur "first_dir" (und natürlich der Inhalt) und "somefile.txt" ( nicht "anotherfile.txt" oder "morefiles.log") entfernt werden.
Frage: Gibt es bessere (elegantere und korrektere) Möglichkeiten, dies zu erreichen?
EDIT:
Ich wurde kürzlich darauf aufmerksam gemacht, dass "Finden" eine bessere Option sein kann:
find * -maxdepth 0 ! -name PATTERN -print0 | xargs -0n1 rm -rf
Diese Lösung behandelt Pfade mit Zeilenvorschubzeichen korrekt.
quelle
Antworten:
Die folgenden Beispiele haben ein
echo
Präfix, damit Sie die Muster testen können, bevor Sie sie tatsächlich verwenden. Entfernen Sie dieecho
, um die zu aktivierenrm -rf
. Ersetzen Sierm -ri
, um zur Bestätigung aufzufordern.ksh hat eine negative Match-Erweiterung für sein Globbing:
Die gleiche Syntax ist in bash verfügbar, wenn Sie die
extglob
Option festlegen :zsh hat hierfür eine eigene Syntax:
Es kann auch die Syntax im ksh- Stil verwenden:
quelle
shopt -s extglob
zu meiner .bashrc-Datei hinzugefügt , daher handelt es sich jetzt um einen Einzeiler ). Perfekt! Ich verspreche eine positive Abstimmung, sobald mein Ruf dies zulässt.Hier ist eine andere
find
Lösung. Ich bin mir nicht sicher, ob dies einen wirklichen Vorteil gegenüber Ihrem hat, aber es brauchtxargs
und berücksichtigt nicht die seltene Möglichkeit, dass * auf zu viele Namen erweitert wird.Ich habe auch hinzugefügt
-type f
, damit nicht versucht wird, Verzeichnisse zu löschen.Warnung:
-delete
ist mächtig. Ich habe einer meiner Testdateien 0 Berechtigungen erteilt und der obige Befehl hat sie ohne zu zögern gelöscht.quelle
-delete
durch, um-print
zu sehen, ob die gewünschten Dateien gefunden werden. Wenn alles in Ordnung ist, verwenden Sie den Befehlsverlauf (z. B. drücken Sie die Aufwärts-Taste), um zum vorherigen Befehl zurückzukehren und sicherzustellen, dass Sie mit denselben Suchfiltern arbeiten.find -delete
nicht leere Verzeichnisse werden nicht entfernt. Beachten Sie auch, dassfind -maxdepth 1
"." (aktuelles Verzeichnis) was wirklich schlecht ist. Obwohl ich Ihre Idee der Beseitigungxargs
mag, könnte manfind -exec
alternativ verwenden.find * -maxdepth 0 ! -name PATTERN -exec rm -rf '{}' \;
Sie können stattdessen dieses Rebol-Skriptbeispiel http://askcodegeneration.com/keep-subversion/ verwenden, das viel verständlicher ist und Benutzerinteraktionen wie Ordnerauswahl und -bestätigung verwalten kann:
quelle