Rimuovere tutte le directory da una directory padre tranne una e i suoi discendenti


8

struttura delle directory

Voglio rimuovere la directory B e D. Ma voglio mantenere C e tutti i suoi file e directory discendenti. Qual è il comando per rimuovere tutte le directory figlio di una directory padre tranne una directory e i suoi figli.

Aiuto apprezzato.


le directory che si desidera rimuovere sono vuote?
Anziano Geek,


Che dire dei file che si trovano direttamente nella directory principale ( Anel tuo esempio)? Eliminali anche o conservali?
Byte Commander

Cosa chiede il Byte Commander, ci sono file in A? o solo directory? Vuoi file regolari in A directory rimosse o solo?
Sergiy Kolodyazhnyy,

Risposte:


6

Quello che vuoi è questo comando:

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/

Spiegazione:

  • find DIRECTORY chiama il comando find per operare su DIRECTORY
  • -mindepth 1 : funziona solo con i contenuti della directory, evita la directory stessa che è di livello 0
  • -maxdepth 1: impedisce la discesa nelle sottodirectory ( rm -rfè comunque ricorsivo, quindi non è necessario scendere nelle sottodirectory per rimuoverle)
  • -type d : cerca solo le directory
  • -not \( -name "keepMe" \) ignora l'elemento con il nome che desideri conservare
  • -exec rm -rf {} \; eseguire la rimozione su ogni elemento trovato

Ottima spiegazione Troppe sequenze di tasti per me ...
Anziano Geek,

1
findè un buon amico qui, ma quelli di Bash fore testsono migliori amici ...>: - D
Comandante di byte

8

Utilizzando le funzionalità glob estese della shell bash (che sono abilitate di default nelle attuali installazioni di Ubuntu), dato

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

5 directories, 0 files

puoi affrontare tutto ciò che esclude Ce i suoi contenuti usando l'espressione glob, ad A/!(C)es

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

Quindi, per rimuovere tutto tranne la directory Ce il suo contenuto, puoi semplicemente usare

rm -rf A/!(C)

in partenza

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

3 directories, 0 files

È incredibile conoscere questa funzione. Funziona benissimo dopo aver eseguito ssh ed eseguito manualmente ma ottengo "" -bash: riga 1: errore di sintassi vicino al token imprevisto ('"quando lo eseguo in remoto tramite ssh $VM_ADDRESS "rm -rf $APP_FOLDER/!(node_modules)". Qualche idea? Grazie mille.
Renato Gama

@renatoargh l' extglobopzione shell è abilitata solo per shell interattive - non sono sicuro di poter forzare ssha farlo
steeldriver

5

Un modo semplice sarebbe usare trash-cli

puoi installarlo con sudo apt-get install trash-cli

una volta installato, è possibile accedere alla directory principale A con cd /Ae quindi immettere il comando in trash B Dcui B e D sono le directory che si desidera rimuovere (finiranno nel cestino per l'unità in cui si trovano, quindi se si commette un errore è possibile recuperare i file)

Testato su Ubuntu 16.04 e 14.04


Questo potrebbe essere semplificato con qualcosa del genere trash ! C?
Sergiy Kolodyazhnyy,

@Serg No trash: cannot trash non existent ! ''
Elder Geek,

@Serg and C viene spazzato via ...
Anziano Geek,

Trovato: stackoverflow.com/q/216995/3701431extglob Tuttavia richiede abilitazione .
Sergiy Kolodyazhnyy,

@Serg A seconda del lavoro a portata di mano che potrebbe essere abbastanza utile! ;-)
Anziano Geek,

4

Usa semplicemente il forciclo di Bash e testper filtrare le directory desiderate e il rm -rfcomando per eliminare ricorsivamente le directory, in questo modo:

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

Ciò scorre su tutti gli elementi (file e directory) all'interno /path/to/parent/ed elimina l'elemento in modo ricorsivo se il suo nome non è uguale a dir_survive. Se la directory principale è la directory corrente, è possibile scrivere solo *come percorso.

Se non si è sicuri e si desidera verificare quali elementi verranno eliminati per primi senza eseguire alcuna azione, è sufficiente sostituire rm -rfil comando nel comando precedente con echoe verranno visualizzati solo i candidati eliminati.

Ecco un esempio:

$ 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.