Supprimer tous les répertoires d'un répertoire parent sauf un et ses descendants

8

structure de répertoire

Je veux supprimer les répertoires B et D. Mais je veux garder C et tous ses fichiers et répertoires descendants. Quelle est la commande pour supprimer tous les répertoires enfants d'un répertoire parent, sauf un répertoire et ses enfants.

Aide appréciée.

Joe Saad
la source
les répertoires que vous souhaitez supprimer sont-ils vides?
Elder Geek
Qu'en est-il des fichiers situés directement dans le répertoire parent ( Adans votre exemple)? Les supprimer également ou les conserver?
Byte Commander
Ce que Byte Commander demande, est-ce qu'il y a des fichiers dans A? ou seulement des répertoires? Voulez-vous des fichiers normaux dans les répertoires A supprimés ou uniquement?
Sergiy Kolodyazhnyy

Réponses:

6

Ce que vous voulez, c'est cette commande:

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

Démo:

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

Explication:

  • find DIRECTORY appeler la commande find pour opérer sur RÉPERTOIRE
  • -mindepth 1 : fonctionne uniquement avec le contenu du répertoire, évitez le répertoire lui-même qui est de niveau 0
  • -maxdepth 1: empêche de descendre dans les sous-répertoires ( rm -rfest récursif de toute façon, nous n'avons donc pas besoin de descendre dans les sous-répertoires pour les supprimer)
  • -type d : recherche uniquement les répertoires
  • -not \( -name "keepMe" \) ignorer l'élément portant le nom que vous souhaitez conserver
  • -exec rm -rf {} \; effectuer la suppression sur chaque élément trouvé
Sergiy Kolodyazhnyy
la source
Grande explication. Trop de frappes pour moi ...
Elder Geek
1
findest un bon ami ici, mais Bash foret testsont de meilleurs amis ...>: - D
Byte Commander
8

Utilisation des fonctionnalités glob étendues du shell bash (qui sont activées par défaut dans les installations Ubuntu actuelles), étant donné

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

5 directories, 0 files

vous pouvez aborder tout ce qui exclut Cet son contenu en utilisant l'expression glob A/!(C)ie

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

Donc, pour tout supprimer sauf le répertoire Cet son contenu, vous pouvez simplement utiliser

rm -rf A/!(C)

en quittant

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

3 directories, 0 files
tournevis
la source
Il est étonnant de connaître cette fonctionnalité. Cela fonctionne très bien après avoir exécuté ssh et manuellement mais j'obtiens "" -bash: ligne 1: erreur de syntaxe près d'un jeton inattendu ('"lorsque je l'exécute à distance via ssh $VM_ADDRESS "rm -rf $APP_FOLDER/!(node_modules)". Des idées? Merci beaucoup.
Renato Gama
@renatoargh, l' extgloboption shell n'est activée que pour les shells interactifs - je ne sais pas si vous pouvez forcer sshà le faire
steeldriver
5

Une façon simple serait d’utiliser trash-cli

vous pouvez l'installer avec sudo apt-get install trash-cli

une fois installé, vous pouvez naviguer vers le répertoire parent A avec cd /Apuis lancer la commande trash B Doù B et D sont les répertoires que vous souhaitez supprimer (ils se retrouveront dans la corbeille du lecteur sur lequel ils se trouvent, donc si vous faites une erreur, vous pouvez récupérer les fichiers)

Testé sous Ubuntu 16.04 et 14.04

Elder Geek
la source
Cela pourrait-il être simplifié avec quelque chose comme trash ! C?
Sergiy Kolodyazhnyy
@Serg Nope trash: cannot trash non existent ! ''
Elder Geek
@Serg et C sont saccagés ...
Elder Geek
Je l'ai trouvé: stackoverflow.com/q/216995/3701431 Il faut extglobcependant l' activer .
Sergiy Kolodyazhnyy
@Serg Selon le travail à effectuer, cela pourrait être très utile! ;-)
Elder Geek
4

Utilisez simplement la forboucle de Bash et testpour filtrer les répertoires souhaités et la rm -rfcommande pour supprimer récursivement les répertoires, comme ceci:

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

Cela itère sur tous les éléments (fichiers et répertoires) à l'intérieur /path/to/parent/et supprime l'élément récursivement si son nom n'est pas égal à dir_survive. Si le répertoire parent est le répertoire actuel, vous ne pouvez écrire qu'en *tant que chemin.

Si vous n'êtes pas sûr et que vous souhaitez tester les éléments qui seront supprimés en premier sans effectuer aucune action, remplacez simplement le rm -rfdans la commande ci-dessus par echoet il ne produira que les candidats à la suppression.

Voici un exemple d'exécution:

$ 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
la source