Entfernen Sie alle Verzeichnisse aus einem übergeordneten Verzeichnis mit Ausnahme eines und seiner Nachkommen

8

Verzeichnisaufbau

Ich möchte Verzeichnis B und D entfernen. Aber ich möchte C und alle seine untergeordneten Dateien und Verzeichnisse behalten. Wie lautet der Befehl zum Entfernen aller untergeordneten Verzeichnisse eines übergeordneten Verzeichnisses mit Ausnahme eines Verzeichnisses und seiner untergeordneten Verzeichnisse?

Hilfe geschätzt.

Joe Saad
quelle
Sind die Verzeichnisse, die Sie entfernen möchten, leer?
Elder Geek
Was ist mit Dateien, die sich direkt im übergeordneten Verzeichnis befinden ( Ain Ihrem Beispiel)? Löschen Sie sie auch oder behalten Sie sie?
Byte Commander
Was Byte Commander fragt, ist, gibt es irgendwelche Dateien in A? oder nur Verzeichnisse? Möchten Sie, dass reguläre Dateien in A entfernt werden oder nur Verzeichnisse?
Sergiy Kolodyazhnyy

Antworten:

6

Was Sie wollen, ist dieser Befehl:

find ~/TESTDIR -mindepth 1 -maxdepth 1 -type d -not \( -name "keepMe" \) -exec rm -rf {} \;

Demo:

# List what's inside directory we want to remove
$ ls
file1  file2  keepMe/  removeA/  removeB/
# Testing what find gives without removing
$ find ~/TESTDIR -mindepth 1 -type d -not \( -name "keepMe" \)               
/home/xieerqi/TESTDIR/removeA
/home/xieerqi/TESTDIR/removeB
# Actual removal and testls
$ find ~/TESTDIR -mindepth 1 -maxdepth 1 -type d -not \( -name "keepMe" \) -exec rm -rf {} \;
$ ls
file1  file2  keepMe/

Erläuterung:

  • find DIRECTORY Rufen Sie den Befehl find auf, um DIRECTORY zu bearbeiten
  • -mindepth 1 : Arbeiten Sie nur mit dem Inhalt des Verzeichnisses. Vermeiden Sie das Verzeichnis selbst auf Ebene 0
  • -maxdepth 1: verhindert das Absteigen in Unterverzeichnisse ( rm -rfist ohnehin rekursiv, sodass wir nicht in Unterverzeichnisse absteigen müssen, um sie zu entfernen)
  • -type d : Suche nur nach Verzeichnissen
  • -not \( -name "keepMe" \) Element mit dem Namen ignorieren, den Sie behalten möchten
  • -exec rm -rf {} \; Entfernen Sie jedes gefundene Objekt
Sergiy Kolodyazhnyy
quelle
Tolle Erklärung. Zu viele Tastenanschläge für mich ...
Elder Geek
1
findist ein guter Freund hier, aber Bash ist forund testsind bessere Freunde ...>: - D
Byte Commander
8

Verwendung der erweiterten Glob- Funktionen der Bash-Shell (die in aktuellen Ubuntu-Installationen standardmäßig aktiviert sind)

$ tree A
A
├── B
├── C
│   ├── ac1
│   └── ac2
└── D

5 directories, 0 files

Sie können alles außer Cund seinen Inhalt mit dem glob-Ausdruck adressieren, A/!(C)dh

$ echo A/!(C)
A/B A/D

Um also alles außer dem Verzeichnis Cund seinem Inhalt zu entfernen , können Sie es einfach verwenden

rm -rf A/!(C)

Verlassen

$ tree A
A
└── C
    ├── ac1
    └── ac2

3 directories, 0 files
Steeldriver
quelle
Es ist erstaunlich, über diese Funktion Bescheid zu wissen. Es funktioniert großartig, nachdem ich ssh und manuell ausgeführt habe, aber ich erhalte "-bash: Zeile 1: Syntaxfehler in der Nähe eines unerwarteten Tokens, ('"wenn ich es remote über ausführe ssh $VM_ADDRESS "rm -rf $APP_FOLDER/!(node_modules)". Irgendwelche Ideen? Vielen Dank.
Renato Gama
@renatoargh die extglobShell - Option ist nur für interaktiven Shells aktiviert - nicht sicher , ob Sie zwingen können , sshdas zu tun
steeldriver
5

Eine einfache Möglichkeit wäre die Verwendung von trash-cli

Sie können es mit installieren sudo apt-get install trash-cli

Nach der Installation können Sie mit zum übergeordneten Verzeichnis A navigieren cd /Aund dann den Befehl eingeben, trash B Dbei dem B und D die Verzeichnisse sind, die Sie entfernen möchten (sie landen im Papierkorb des Laufwerks, auf dem sie sich befinden. Wenn Sie also einen Fehler machen, können Sie dies tun Dateien wiederherstellen)

Getestet unter Ubuntu 16.04 und 14.04

Elder Geek
quelle
Könnte dies mit so etwas vereinfacht werden trash ! C?
Sergiy Kolodyazhnyy
@ Serg Nope trash: cannot trash non existent ! '`
Elder Geek
@ Serg und C wird verwüstet ...
Elder Geek
Gefunden: stackoverflow.com/q/216995/3701431 Es muss jedoch aktiviert werden extglob.
Sergiy Kolodyazhnyy
@Serg Je nach Job kann das sehr nützlich sein! ;-)
Elder Geek
4

Verwenden Sie einfach die Bash- forSchleife und testfiltern Sie die gewünschten Verzeichnisse und den rm -rfBefehl zum rekursiven Löschen von Verzeichnissen wie folgt:

for x in /path/to/parent/*; do test "$x" != "dir_survive" && rm -rf "$x"; done

Dies durchläuft alle Elemente (Dateien und Verzeichnisse) im Inneren /path/to/parent/und löscht das Element rekursiv, wenn sein Name nicht gleich ist dir_survive. Wenn das übergeordnete Verzeichnis das aktuelle Verzeichnis ist, dürfen Sie nur *als Pfad schreiben .

Wenn Sie sich nicht sicher sind und testen möchten, welche Elemente zuerst gelöscht werden, ohne etwas zu unternehmen, ersetzen Sie einfach das rm -rfim obigen Befehl angegebene durch echound es werden nur die Löschkandidaten ausgegeben.

Hier ist ein Beispiellauf:

$ tree
.
├── dir1
│   ├── subdir1
│   │   ├── file1
│   │   └── file2
│   └── subdir2
│       ├── file1
│       └── file2
├── dir2
│   ├── subdir1
│   │   ├── file1
│   │   └── file2
│   └── subdir2
│       ├── file1
│       └── file2
└── dir_survive
    ├── subdir1
    │   ├── file1
    │   └── file2
    └── subdir2
        ├── file1
        └── file2

9 directories, 12 files

$ for x in *; do test "$x" != "dir_survive" && rm -rf "$x"; done

$ tree
.
└── dir_survive
    ├── subdir1
    │   ├── file1
    │   └── file2
    └── subdir2
        ├── file1
        └── file2

3 directories, 4 files
Byte Commander
quelle