Comment supprimer tous les répertoires vides d'un sous-arbre? J'ai utilisé quelque chose comme
find . -type d -exec rmdir {} 2>/dev/null \;
mais je dois être exécuté plusieurs fois afin de supprimer les répertoires contenant uniquement des répertoires vides. De plus, c'est assez lent, surtout sous cygwin.
Combinant GNU find
options et prédicats, cette commande devrait faire le travail:
find . -type d -empty -delete
-type d
restreint aux répertoires-empty
se limite aux vides-delete
supprime chaque répertoireL'arbre est parcouru à partir des feuilles sans avoir besoin de spécifier -depth
comme le laisse entendre -delete
.
Liste les répertoires profondément imbriqués en premier.
find . -depth -type d -exec rmdir {} \; 2>/dev/null
(Notez que la redirection s'applique à la commande find
dans son ensemble, pas seulement à rmdir
. La redirection uniquement pour rmdir
entraînerait un ralentissement important car vous auriez besoin d'invoquer un Shell intermédiaire.)
Vous pouvez éviter d'exécuter rmdir
sur des répertoires non vides en passant le -empty
prédicat à rechercher. GNU find teste le répertoire quand il est sur le point d'exécuter la commande, donc les répertoires qui viennent d'être vidés seront récupérés.
find . -depth -type d -empty -exec rmdir {} \;
Une autre façon d'accélérer serait de regrouper les invocations rmdir
. Les deux sont susceptibles d'être sensiblement plus rapides que l'original, en particulier sous Cygwin. Je ne m'attends pas à beaucoup de différence entre ces deux.
find . -depth -type d -print0 | xargs -0 rmdir 2>/dev/null
find . -depth -type d -exec rmdir {} + 2>/dev/null
La méthode la plus rapide dépend du nombre de répertoires non vides dont vous disposez. Vous ne pouvez pas combiner -empty
avec des méthodes de regroupement des appels, car les répertoires qui ne contiennent que des répertoires vides ne sont pas vides au moment où find
les examine.
Une autre méthode consisterait à exécuter plusieurs passes. Que ce soit plus rapide dépend de beaucoup de choses, y compris si toute la hiérarchie des répertoires peut rester dans le cache disque entre les exécutions find
.
while [ -n "$(find . -depth -type d -empty -print -exec rmdir {} +)" ]; do :; done
Vous pouvez également utiliser zsh. Le qualificatif globF
correspond aux répertoires non vides, donc /^F
correspond à des répertoires vides. Les répertoires qui ne contiennent que des répertoires vides ne peuvent pas être mis en correspondance si facilement.
while rmdir **/*(/N^F); do :; done
(Cela se termine lorsque rmdir
reçoit une ligne de commande vide.)
Si vous clouez juste un -p
sur votre rmdir
, cela fonctionnera en un seul passage. Ce ne sera ni joli ni optimal, mais il devrait tout avoir. Cela indique à rmdir de supprimer tous les répertoires parents non vides de celui que vous supprimez.
Vous pouvez économiser un peu en ajoutant le -empty
test pour trouver, donc ça ne dérange pas avec les répertoires non vides.
find . -depth -type d -exec rmdir {} +
est la réponse la plus simple et conforme à cette question.
Les autres réponses données ici dépendent malheureusement toutes d'améliorations spécifiques au fournisseur qui n'existent pas sur tous les systèmes.
J'utilise ces alias pour les commandes find
fréquemment utilisées, en particulier lorsque je nettoie l'espace disque à l'aide de dupegur, où la suppression des doublons peut entraîner de nombreux répertoires vides.
Commentaires à l'intérieur .bashrc
donc je ne les oublierai pas plus tard quand je devrai le modifier.
# find empty directories
alias find-empty='find . -type d -empty'
# fine empty/zero sized files
alias find-zero='find . -type f -empty'
# delete all empty directories!
alias find-empty-delete='find-empty -delete'
# delete empty directories when `-delete` option is not available.
# output null character (instead of newline) as separator. used together
# with `xargs -0`, will handle filenames with spaces and special chars.
alias find-empty-delete2='find-empty -print0 | xargs -0 rmdir -p'
# alternative version using `-exec` with `+`, similar to xargs.
# {}: path of current file
# +: {} is replaced with as many pathnames as possible for each invocation.
alias find-empty-delete3='find-empty -exec rmdir -p {} +'
# for removing zero sized files, we can't de-dupe them automatically
# since they are technically all the same, so they are typically left
# beind. this removes them if needed.
alias find-zero-delete='find-zero -delete'
alias find-zero-delete2='find-zero -print0 | xargs -0 rm'
alias find-zero-delete3='find-zero -exec rm {} +'
find . -type d -printf "%d %p\n" |\ sort -nr |\ Perl -pe 's/^\d+\s//;' |\ while read dir; do \ (rmdir "$dir" > /dev/null 2>&1); \ done
Voici comment ça fonctionne:
rmdir
sur la liste un par un