it-swarm.com.de

Löschen Sie alle Ordner in einem Ordner mit Ausnahme eines Ordners mit einem bestimmten Namen

Ich muss alle Ordner in einem Ordner mit einem täglichen Skript löschen. Der Ordner für diesen Tag muss verlassen werden.

Ordner 'myfolder' hat 3 Unterordner: 'test1', 'test2' und 'test3' Ich muss alle außer 'test2' löschen.

Ich versuche hier den genauen Namen zu finden:

find /home/myfolder -type d ! -name 'test2' | xargs rm -rf

OR

find /home/myfolder -type d ! -name 'test2' -delete

Dieser Befehl versucht immer auch den Hauptordner 'myfolder' zu löschen! Gibt es eine Möglichkeit, dies zu vermeiden?

19
Riju Mahna

Dadurch werden alle Ordner in ./myfolder Gelöscht, außer dass ./myfolder/test2 Und der gesamte Inhalt erhalten bleiben:

find ./myfolder -mindepth 1 ! -regex '^./myfolder/test2\(/.*\)?' -delete

Wie es funktioniert

  • find startet einen Suchbefehl.
  • ./myfolder Weist find an, mit dem Verzeichnis ./myfolder Und seinem Inhalt zu beginnen.

  • -mindepth 1 Nicht mit ./myfolder Selbst übereinstimmen, sondern nur mit den Dateien und Verzeichnissen darunter.

  • ! -regex '^./myfolder/test2\(/.*\)?' weist find an, alle Dateien oder Verzeichnisse auszuschließen (!), die dem regulären Ausdruck ^./myfolder/test2\(/.*\)? entsprechen. ^ Entspricht dem Anfang des Pfadnamens. Der Ausdruck (/.*\)? Entspricht entweder (a) einem Schrägstrich gefolgt von irgendetwas oder (b) gar nichts.

  • -delete Weist find an, die übereinstimmenden (dh nicht ausgeschlossenen) Dateien zu löschen.

Beispiel

Stellen Sie sich eine Verzeichnisstruktur vor, die so aussieht.

$ find ./myfolder
./myfolder
./myfolder/test1
./myfolder/test1/dir1
./myfolder/test1/dir1/test2
./myfolder/test1/dir1/test2/file4
./myfolder/test1/file1
./myfolder/test3
./myfolder/test3/file3
./myfolder/test2
./myfolder/test2/file2
./myfolder/test2/dir2

Wir können den Befehl find (ohne -delete) Ausführen, um zu sehen, was dazu passt:

$ find ./myfolder -mindepth 1 ! -regex '^./myfolder/test2\(/.*\)?'
./myfolder/test1
./myfolder/test1/dir1
./myfolder/test1/dir1/test2
./myfolder/test1/dir1/test2/file4
./myfolder/test1/file1
./myfolder/test3
./myfolder/test3/file3

Wir können überprüfen, ob dies funktioniert hat, indem wir uns die verbleibenden Dateien ansehen:

$ find ./myfolder
./myfolder
./myfolder/test2
./myfolder/test2/file2
./myfolder/test2/dir2
33
John1024

Bash verwenden :

shopt -s extglob
rm -r myfolder/!(test2)/

Beispiel:

$ tree myfolder/
myfolder/
├── test1
│   └── file1
├── test2
│   └── file2
└── test3
    └── file3

$ echo rm -r myfolder/!(test2)
rm -r myfolder/test1 myfolder/test3
$ rm -r myfolder/!(test2)
$ tree myfolder/
myfolder/
└── test2
    └── file2

1 directory, 1 file
10
Jeff Schaller

tl; dr

find ./myfolder -mindepth 1 -maxdepth 1 -type d -not -name test2 \
     -exec echo rm -rf '{}' \;

Entfernen Sie das Echo, wenn Sie mit der Liste der Dateien zufrieden sind.


Durch die Verwendung von -mindepth 1 Wird sichergestellt, dass das Verzeichnis top nicht ausgewählt ist.

$ find ./myfolder -mindepth 1 -type d
./myfolder/test2
./myfolder/test2/one
./myfolder/test2/two
./myfolder/test
./myfolder/test/a1
./myfolder/test/a1/a2
./myfolder/test/a1/a2/a3

Aber ein -not -name test2 Wird nicht Unterverzeichnisse in test2 Vermeiden:

$ find ./myfolder -mindepth 1 -type d -not -name 'test2'
./myfolder/test2/one
./myfolder/test2/two
./myfolder/test
./myfolder/test/a1
./myfolder/test/a1/a2
./myfolder/test/a1/a2/a3

Dazu benötigen Sie so etwas wie Prune:

$ find ./myfolder -mindepth 1 -name test2 -Prune -o -type d -print
./myfolder/test
./myfolder/test/a1
./myfolder/test/a1/a2
./myfolder/test/a1/a2/a3

Aber benutze nicht delete, da es depth impliziert und das wird vom längsten Pfad gelöscht:

$ find ./myfolder -depth -mindepth 1 -name test2 -Prune -o -type d -print
./myfolder/test/a1/a2/a3
./myfolder/test/a1/a2
./myfolder/test/a1
./myfolder/test

Verwenden Sie entweder rm -rf (Entfernen Sie das echo, wenn Sie es tatsächlich löschen möchten):

$ find ./myfolder -mindepth 1 -name test2 -Prune -o -type d -exec echo rm -rf '{}' \;
rm -rf ./myfolder/test
rm -rf ./myfolder/test/a1
rm -rf ./myfolder/test/a1/a2
rm -rf ./myfolder/test/a1/a2/a3

Oder auch benutze maxdepth, wenn du nur Verzeichnisse (und alles darin) löschen musst (entferne das echo, um es tatsächlich zu löschen):

$ find ./myfolder -mindepth 1 -maxdepth 1 -type d -not -name test2 -exec echo rm -rf '{}' \;
rm -rf ./myfolder/test

Ein -delete Schlägt immer noch fehl, wenn das Verzeichnis nicht leer ist:

$ find ./myfolder -mindepth 1 -maxdepth 1 -type d -not -name test2 -delete
find: cannot delete ‘./myfolder/test’: Directory not empty
5
Isaac

Wenn Sie zsh verwenden, können Sie:

setopt extended_glob # if you don't have it enabled

rm -rf myfolder/^test2
2
JoL

Getestet mit dem folgenden Befehl und es hat gut funktioniert

find  /home/myfolder -maxdepth 1 -type d ! -iname test2 -exec rm -rvf {} \;
0