web-dev-qa-db-fra.com

Comment supprimer tous les sous-dossiers de premier niveau dont le nom ne contient pas de chaîne spécifiée

Je sais qu'il y a beaucoup de réponses à vos questions sur la suppression de tous les fichiers avec ou sans une certaine chaîne dans leurs noms, ainsi que des explications sur la suppression de tous les sous-dossiers avec une certaine chaîne dans leurs noms.

Pourtant, il n'y a pas de questions sur la façon de supprimer tous les sous-dossiers sans une certaine chaîne dans leurs noms.

Donc, comme j'ai récemment rencontré un tel problème, y at-il une commande rapide qui aidera à cette situation? Un script bash serait également suffisant.

EDIT:

Par sous-dossiers, je ne parlais que des sous-dossiers de premier niveau, car je ne souhaite pas supprimer les sous-dossiers de deuxième ou troisième niveau, qui peuvent avoir des noms sans la chaîne, des sous-dossiers de premier niveau avec la ficelle.

3
PyGeek03

Supposons que vous souhaitiez démarrer find dans le répertoire actuel et limitez-le au premier niveau de sous-répertoires:

find . -maxdepth 1

La commande find a un indicateur utile -not (ou !) qui annule le test suivant. Donc, afin de trouver un nom qui contient pas contient une sous-chaîne, ajoutez

-not -name "*substring*"

IMPORTANT: vous voudrez également exclure le répertoire actuel. Sinon, tout le répertoire en cours serait supprimé.

-not -name "."

Ensuite, vous voulez tester uniquement les répertoires:

-type d

Et, si tout va bien, vous voulez supprimer ces répertoires:

-exec rm -rf {} \;

qui dit "pour tous les répertoires trouvés, exécutez cette commande". Le {} est un espace réservé pour le nom du répertoire (y compris le chemin complet, donc il fonctionne sur le bon). \; indique la fin de la commande à exécuter.

Résumant:

find . -maxdepth 1 -not -name "*substring*" -not -name "." -type d -exec rm -rf {} \;

devrait marcher. Mais d’abord, essayez-le sans la partie -exec.

9
Jos

Les opérateurs extended glob du bash shell peuvent effectuer la négation de modèle, par exemple. donné

$ tree .
.
├── subdir
│   ├── other file
│   └── somefile
├── subdirbar
│   ├── other file
│   └── somefile
├── subdirbaz
│   ├── other file
│   └── somefile
└── subdirfoo
    ├── other file
    └── somefile

4 directories, 8 files

puis, si l'extension étendue est activée (shopt -s extglob)

$ rm -rf !(*foo*)

supprime (récursivement) tous les répertoires de niveau supérieur ne contenant pas la chaîne foo, en laissant

$ tree
.
└── subdirfoo
    ├── other file
    └── somefile

1 directory, 2 files

Cependant, cela supprime également les fichiers dont les noms ne contiennent pas foo au niveau supérieur. Les globs étendus AFAIK bash ne peuvent pas distinguer les fichiers des répertoires - mais zsh fournit qualificatifs de glob, qui permettent, par exemple, de donné

 % tree
.
├── foofile
├── other file
├── somefile
├── subdir
│   ├── other file
│   └── somefile
├── subdirbar
│   ├── other file
│   └── somefile
├── subdirbaz
│   ├── other file
│   └── somefile
└── subdirfoo
    ├── other file
    └── somefile

4 directories, 11 files

puis dans zsh

 % setopt EXTENDED_GLOB

 % ls -d (^(*foo*))   
other file  somefile  subdir  subdirbar  subdirbaz

alors que l'ajout du qualificatif de répertoire (/)

 % ls -d (^(*foo*))(/)
subdir  subdirbar  subdirbaz

alors

 % rm -rf (^(*foo*))(/)

supprime uniquement répertoires dont les noms n'incluent pas la chaîne foo, en laissant les fichiers non modifiés intacts.

 % tree
.
├── foofile
├── other file
├── somefile
└── subdirfoo
    ├── other file
    └── somefile

1 directory, 5 files
4
steeldriver