Usuń wszystkie katalogi z katalogu nadrzędnego oprócz jednego i jego potomków

8

struktura katalogów

Chcę usunąć katalog B i D. Ale chcę zachować C i wszystkie jego potomne pliki i katalogi. Jaka jest komenda usuwania wszystkich katalogów potomnych katalogu nadrzędnego oprócz jednego katalogu i jego potomków.

Pomoc doceniona.

Joe Saad
źródło
czy katalogi, które chcesz usunąć, są puste?
Elder Geek
Co z plikami znajdującymi się bezpośrednio w katalogu nadrzędnym ( Aw twoim przykładzie)? Usunąć je również czy zachować?
Bajt Dowódca
Pyta Byte Commander, czy w A są jakieś pliki? czy tylko katalogi? Czy chcesz usunąć zwykłe pliki z katalogu A czy tylko katalogi?
Sergiy Kolodyazhnyy

Odpowiedzi:

6

To, czego chcesz, to polecenie:

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

Próbny:

# 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/

Wyjaśnienie:

  • find DIRECTORY wywołaj polecenie find, aby operować na KATALOGU
  • -mindepth 1 : działa tylko z zawartością katalogu, unikaj samego katalogu, który jest na poziomie 0
  • -maxdepth 1: zapobiega zejściu do podkatalogów ( rm -rfzresztą jest rekurencyjny, więc nie musimy schodzić do podkatalogów, aby je usunąć)
  • -type d : szukaj tylko katalogów
  • -not \( -name "keepMe" \) zignoruj ​​element o nazwie, którą chcesz zachować
  • -exec rm -rf {} \; usuń każdy znaleziony element
Sergiy Kolodyazhnyy
źródło
Świetne wyjaśnienie. Jednak dla mnie za dużo naciśnięć klawiszy ...
Starszy Geek
1
findjest dobrym przyjacielem, ale Bash fori testlepsi przyjaciele ...>: - D
Byte Commander
8

Korzystanie z rozszerzonych funkcji globalnej powłoki bash (które są domyślnie włączone w bieżących instalacjach Ubuntu), podane

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

5 directories, 0 files

możesz zająć się wszystkim z wyłączeniem Ci jego zawartością za pomocą wyrażenia glob, A/!(C)tj

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

Aby usunąć wszystko oprócz katalogu Ci jego zawartości, możesz po prostu użyć

rm -rf A/!(C)

odejście

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

3 directories, 0 files
steeldriver
źródło
To niesamowite wiedzieć o tej funkcji. Działa świetnie po ssh i ręcznym uruchomieniu, ale pojawia się komunikat „” -bash: linia 1: błąd składni w pobliżu nieoczekiwanego tokena, ('"gdy uruchamiam go zdalnie za pośrednictwem ssh $VM_ADDRESS "rm -rf $APP_FOLDER/!(node_modules)". Masz jakieś pomysły? Bardzo dziękuję.
Renato Gama
@renatoargh extglobopcja powłoki jest włączona tylko dla powłok interaktywnych - nie wiem, czy można zmusić sshdo zrobienia tego
steeldriver
5

Jednym prostym sposobem byłoby użycie trash-cli

możesz go zainstalować za pomocą sudo apt-get install trash-cli

po zainstalowaniu możesz przejść do katalogu nadrzędnego A, cd /Aa następnie wydać polecenie, w trash B Dktórym B i D są katalogami, które chcesz usunąć (trafią do kosza na dysku, na którym się znajdują, więc jeśli popełnisz błąd, możesz to zrobić odzyskać pliki)

Testowane pod Ubuntu 16.04 i 14.04

Starszy Geek
źródło
Czy można to uprościć za pomocą czegoś takiego trash ! C?
Sergiy Kolodyazhnyy
@Serg Nope trash: cannot trash non existent ! ''
Starszy Geek
@Serg and C zostaje zniszczony ...
Starszy Geek
Znaleziono: stackoverflow.com/q/216995/3701431 Wymaga to extglobjednak włączenia .
Sergiy Kolodyazhnyy
@Serg W zależności od wykonywanej pracy może to być bardzo przydatne! ;-)
Starszy Geek
4

Wystarczy użyć forpętli Basha i testprzefiltrować pożądane katalogi oraz rm -rfpolecenie rekurencyjnego usuwania katalogów, tak jak to:

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

Powoduje to iterację wszystkich elementów (plików i katalogów) w środku /path/to/parent/i rekurencyjnie usuwa element, jeśli jego nazwa nie jest równa dir_survive. Jeśli katalog nadrzędny jest katalogiem bieżącym, możesz pisać tylko *jako ścieżkę.

Jeśli nie masz pewności i chcesz przetestować, które elementy zostaną najpierw usunięte bez podejmowania jakichkolwiek działań, po prostu zamień rm -rfpowyższe polecenie na, echoa wyświetli tylko kandydatów do usunięcia.

Oto przykładowy przebieg:

$ 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
Bajt Dowódca
źródło