Comment supprimer récursivement des répertoires avec un caractère générique?

52

Je travaille via SSH sur une édition WD My Book World. Fondamentalement, je voudrais commencer à un niveau de répertoire particulier et supprimer récursivement tous les sous-répertoires correspondants .Apple*. Comment pourrais-je m'y prendre?

j'ai essayé

rm -rf .Apple* et rm -fR .Apple*

ni les répertoires supprimés correspondant à ce nom dans les sous-répertoires.

codedog
la source

Réponses:

73

find est très utile pour effectuer sélectivement des actions sur tout un arbre.

find . -type f -name ".Apple*" -delete

Ici, le -type fvérifie que c'est un fichier, pas un répertoire, et peut ne pas être exactement ce que vous voulez, car il ignorera également les liens symboliques, les sockets et d'autres choses. Vous pouvez utiliser ! -type d, ce qui signifie littéralement pas des répertoires, mais vous pouvez également supprimer des caractères et bloquer des périphériques. Je suggérerais de regarder le -typeprédicat sur la page de manuel pour find.

Pour le faire strictement avec un caractère générique, vous avez besoin d’une prise en charge avancée du shell. Bash v4 a l' globstaroption , qui vous permet de faire correspondre récursivement les sous-répertoires en utilisant **. zshet kshsoutenir également ce modèle. En utilisant cela, vous pouvez faire rm -rf **/.Apple*. Ce n'est pas standard POSIX, et pas très portable, donc je voudrais éviter de l'utiliser dans un script, mais pour une action shell interactive unique, c'est très bien.

Shawn J. Goff
la source
3
Je peux aller find . -type d -name .Apple*au travail - il répertorie tous les dossiers. Cependant, cela échoue lorsque j'ajoute -deleteà la fin. Il ne fait que revenir avec le résumé de l'utilisation. Il fonctionne sur BusyBox v1.1.1. Cela fait-il une différence?
Codedog
1
-deleten'est pas POSIX non plus. **a été introduit par zshau début des années 90. C'est maintenant (par ordre chronologique d'apparition) également dans ksh93, fish, bash et tcsh.
Stéphane Chazelas
1
+1 pourrm -rf **/.Apple*
Andriy Boyko
1
@codedog, si -deletene fonctionne pas, utilisez -exec rm -f {} +plutôt.
Wildcard
1
Pouvez-vous arriver findà être commenté alors qu'il supprime? Je suppose que la méthode "globstar" le ferait en ajoutant le -vcommutateur.
Demis
17

J'ai rencontré des problèmes d'utilisation findavec en -deleteraison du comportement intentionnel de find(c'est-à-dire refuser de supprimer si le chemin commence par ./, ce qu'ils font dans mon cas), comme indiqué dans sa page de manuel:

 -delete

Supprimer les fichiers et / ou répertoires trouvés. Retourne toujours vrai. Cela s'exécute à partir du répertoire de travail en cours lorsque find revient dans l'arborescence. Il ne tentera pas de supprimer un nom de fichier avec un caractère "/" dans son chemin relatif à "." pour des raisons de sécurité.
Le traitement de traversée en profondeur d'abord est impliqué par cette option.
Suivre les liens symboliques est incompatible avec cette option.

Au lieu de cela, j'ai pu faire

find . -type d -name 'received_*_output' -exec rm -r {} +

En ce qui concerne votre cas, il semble que la solution soit la citation du glob (astérisque, *), mais je voulais donner ma réponse au cas où quelqu'un d'autre aurait le même problème.

NOTE: Auparavant, ma réponse était de procéder comme suit, mais @Wildcard a souligné les failles de sécurité dans les commentaires.

find . -type d -name 'received_*_output' | xargs rm -r
Tapoter
la source
1
Aucune bonne raison d'utiliser xargsici. -exec rm -r {} \;ou, mieux, -exec rm -r {} +fera aussi bien sans manquer aux noms de fichiers de caractères spéciaux. Voir Pourquoi la boucle sur la sortie de find est-elle une mauvaise pratique?
Wildcard
C'est bon à savoir. Ne valez pas un downvote, IMO, car la commande effectue toujours le travail, mais l'optimisation des performances est appréciée.
Pat
1
S'il s'agissait simplement d'une optimisation des performances, je serais d'accord avec vous, mais ce n'est pas le cas. C'est un trou de sécurité. Vous ne gérez pas correctement les fichiers dont les noms comportent des espaces, et un nom de fichier créé de manière malveillante entraînera une perte de données. Voir également Implications pour la sécurité de l'oubli de citer une variable dans les shell bash / POSIX ; une partie est applicable et peut au moins vous donner une idée du type de problèmes dont je parle.
Wildcard
Essayez mkdir -p $'blah\nDocuments\n/etc\n/home\n/received__output'dans votre répertoire, puis réexécutez la même commande si vous ne croyez pas qu'il existe un risque de perte de données. Ou, puisque la question est sur Mac OS, mkdir -p $'blah\nDocuments\n/Users\n/Applications\n/received__output'. ( Attention: vous effacerez tous vos fichiers si vous le faites. C'est un peu ce que je veux dire.)
Wildcard
0

Ce qui est possible, c’est que votre commande rm / find n’est pas un problème, mais que l’utilisateur auquel vous êtes connecté ne dispose pas en réalité des autorisations de suppression. Utilisez cette option ls -lpour répertorier les éléments avec leurs autorisations, et vous pouvez identifier qui vous êtes avec les commandes idet groups(l'une ou l'autre doit être disponible). Si vous êtes le "mauvais utilisateur", vous devrez soit modifier les autorisations / la propriété des fichiers, soit basculer vers un autre utilisateur.

Froztbyte
la source
0

Essayer:

shopt -s dotglob           # using Bash
printf '%s\n' ./.Apple*    # test
#rm -rf ./.Apple*    
Jan
la source
1
dotglobest inutile ici. Voir cette page pour un exemple de ce que fait le dotglob.
Amphetamachine
-1

Commande simple:

rm `find ./ -name '.Apple*'` -rf

Bonne chance!

KimKha
la source
4
Ceci est extrêmement sujet aux erreurs, find a -exec key.
Anton Barkovsky