Ausschluss bestimmter Dateien und Verzeichnisse beim Löschen von Dateien

11

Mein oberstes Verzeichnis ist data. dataenthält mehrere Verzeichnisse und diese Verzeichnisse haben Unterverzeichnisse. Ich muss alle Dateien und Verzeichnisse data/außer einigen Dateien in einigen Verzeichnissen entfernen .

Zu den Daten gehören beispielsweise die Verzeichnisse 100und 101. Ich möchte nur a.txtund b.txtDateien in 100/und c.txtund d.txtDateien in behalten, 101/während alle anderen Dateien und Verzeichnisse in 100und entfernt werden 101.

Beispiel:

.
├── 100
   ├── a.txt
   ├── b.txt
   ├── c.txt
   └── d.txt
└── 101
    ├── a.txt
    ├── b.txt
    ├── c.txt
    └── d.txt

Ich verwende den rm -rf !(a.txt|b.txt)Befehl, kann diesen Befehl jedoch nicht automatisch für jedes Verzeichnis anwenden.

tiefes Blau
quelle

Antworten:

12

Wie Sie bereits herausgefunden haben, können Sie die folgende extglobFunktion verwenden:

shopt -s extglob

Auf diese Weise können Übereinstimmungen ausgeschlossen werden, sodass Sie Folgendes tun können:

rm 100/!([ab].txt) 101/!([cd].txt)

Es ist eine gute Idee, es echozuerst zu testen . Dieses Beispiel stimmt mit allem überein, 100/was nicht a.txtoder ist, b.txtund mit allem, 101/was nicht c.txtoder ist d.txt. Wenn die gleichen Regeln auch für 100/gelten, 102/können Sie z.

10[02]/!([ab].txt) # or
{100,102}/!([ab].txt)
Dessert
quelle
Ich habe gerade ein Beispiel für 100 und 101 Verzeichnisse gegeben, aber in Wirklichkeit beträgt die Anzahl der Unterverzeichnisse fast 20. Gibt es eine Möglichkeit, den obigen Code für jedes Verzeichnis zu implementieren, ohne jeden Verzeichnisnamen in den Hauptordner zu schreiben?
Deepblue
@deepblue Bitte geben Sie in Ihrer Frage ( Bearbeiten ) ein genaues Beispiel dafür an. Es ist besonders unklar, wie Sie rmwissen sollten, welche Dateien in welchen Verzeichnissen aufbewahrt werden sollen, wenn Sie dies nicht angeben möchten.
Nachtisch
7

Sie könnten dafür verwenden find. Sie können Tests findmit -notoder negieren !. Dadurch werden Übereinstimmungen ausgeschlossen, anstatt sie zu finden.

Sie sollten darauf achten, keines der übergeordneten Verzeichnisse der Dateien, die Sie behalten möchten, zu löschen, insbesondere das aktuelle Verzeichnis. . Lesen Sie daher die Ausgabe sorgfältig durch, bevor Sie sie löschen.

Anhand Ihres Beispiels können Sie so etwas aus dem dataVerzeichnis heraus tun .

find ! -path . ! -path ./100 ! -path ./101 ! -path "./100/[ab].txt" ! -path "./101/[cd].txt"

Fügen Sie ! -path ./path/to/dirfür jeden Pfad, den Sie löschen möchten, ein hinzu. Sie können Metazeichen wie verwenden *, aber stellen Sie sicher, dass Sie den Ausdruck zitieren, wenn Sie dies tun, z"./path*dir" um unerwünschte Erweiterungen zu verhindern.

findist standardmäßig rekursiv. Auch wenn wir ./100hier nicht finden , werden wir alle Inhalte finden , es sei denn, sie stimmen mit dem Muster überein [ab].txt. Wenn Sie nicht alle Namen finden können, die Sie behalten möchten, fügen Sie einen weiteren Test hinzu:

! -path "./100/[ab].txt" ! -path ./100/foo

Dies wird nicht a.txtoder b.txtoder finden foo, aber es werden alle anderen Dateien gefunden.

Wenn Sie sicher sind, dass Sie sehen, was Sie wollen, können Sie -deleteam Ende hinzufügen , um die gefundenen Dateien zu löschen:

find ! -path . ! -path ./100 ! -path ./101 ! -path "./100/[ab].txt" ! -path "./101/[cd].txt" -delete
Zanna
quelle