Comment faire une boucle par le biais d'un répertoire de façon récursive pour supprimer des fichiers avec certaines extensions
J'ai besoin de boucle à travers un répertoire de façon récursive et de supprimer tous les fichiers avec l'extension .pdf and.doc je suis de la gestion de la boucle à travers un répertoire de façon récursive, mais ne parvenant pas à filtrer les fichiers avec le fichier extensions.
Mon code jusqu'à présent
#/bin/sh
SEARCH_FOLDER="/tmp/*"
for f in $SEARCH_FOLDER
do
if [ -d "$f" ]
then
for ff in $f/*
do
echo "Processing $ff"
done
else
echo "Processing file $f"
fi
done
J'ai besoin d'aide pour remplir le code, car je ne suis pas aller nulle part.
- Je sais que c'est une mauvaise forme d'exécuter du code sans le comprendre, mais beaucoup de gens viennent sur ce site pour apprendre les scripts bash. Je suis arrivé ici par googler "scripts bash fichiers de manière récursive", et presque couru une seule de ces réponses (juste pour tester la récursivité) sans s'en rendre compte, il serait de supprimer les fichiers. Je sais
rm
est une partie de l'OP du code, mais ce n'est pas réellement pertinente à la question posée. Je pense que ce serait plus sûr si des réponses ont été formulées à l'aide d'un inoffensif commande commeecho
. - Question similaire ici: stackoverflow.com/questions/41799938/...
- eu une expérience similaire, tout à fait d'accord et a changé le titre
Vous devez vous connecter pour publier un commentaire.
find
est juste fait pour que.-delete
option.find ... -print0 | xargs -0 ...
, pas cru trouver | xargs pour éviter les problèmes avec les fichiers contenant des retours à la ligne.xargs
sans options, est presque toujours de mauvais conseils, et ce n'est pas une exception. Utilisationfind … -exec
à la place.Comme une suite de mouviciel réponse, vous pourriez aussi le faire comme pour la boucle, au lieu d'utiliser xargs. Je trouve souvent xargs lourd, surtout si j'ai besoin de faire quelque chose de plus compliqué à chaque itération.
Comme un certain nombre de personnes ont commenté, ce sera un échec si il y a des espaces dans les noms de fichiers. Vous pouvez contourner ce problème en installant provisoirement l'IFS (internal field élément de séparation) pour le caractère de saut de ligne. Cette échoue également si il ya des caractères génériques
\[?*
dans les noms de fichier. Vous pouvez contourner ce problème en désactivant temporairement expansion des caractères génériques (globbing).Si vous avez des retours à la ligne dans vos noms de fichiers, puis qui ne fonctionne pas, soit. Vous êtes mieux avec un xargs solution basée sur:
(L'échappé crochets sont nécessaires ici pour la
-print0
s'appliquent à la foisor
clauses.)GNU et *BSD trouver a également un
-delete
d'action, qui devrait ressembler à ceci:for f in $(find ...)
. il suffit de ne pas utiliser cette méthode.find
a un-delete
drapeau. Pourquoi ne pas l'utiliser?Sans
find
:/tmp/*
sont des fichiers dir et/tmp/**/*
sont des fichiers dans des sous-dossiers. Il est possible que vous ayez à permettre globstar option (shopt -s globstar
).Donc pour la question, le code devrait ressembler à ceci:
À noter que cela nécessite bash ≥4.0 (ou zsh, sans
shopt -s globstar
, ou ksh avecset -o globstar
au lieu deshopt -s globstar
). En outre, dans bash <4.3, cette traverse des liens symboliques vers des répertoires, ainsi que des répertoires, ce qui n'est généralement pas souhaitable.for f in /tmp/**
sera suffisant. Inclut les fichiers de /tmp dir.for f in /tmp/*.{pdf,doc} tmp/**/*.{,pdf,doc} ; do
shopt -s dotglob
si les fichiers cachés doit être trouvé; et si vous avez un répertoire vide avec l'une des extensions, votre commande supprimer qui, trop peut-être tester sif
est un fichier,[[ -f $f ]] && rm "$f"
?**
est une belle extension, mais pas de portable à POSIXsh
. (Cette question est étiqueté bash mais il serait bon de souligner que, contrairement à plusieurs des solutions ici, c'est vraiment Bash seule. Ou bien, il travaille dans plusieurs autres coquilles, aussi.)Si vous voulez faire quelque chose de manière récursive, je vous suggère d'utiliser la récursivité (oui, vous pouvez le faire à l'aide de meules et ainsi de suite, mais bon).
Cela dit,
find
est probablement un meilleur choix comme cela a déjà été suggéré.Voici un exemple d'utilisation de la coquille (
bash
):Cela ne veut pas répondre directement à votre question, mais vous pouvez résoudre votre problème avec un one-liner:
Certaines versions de trouver (GNU, BSD) ont un
-delete
action que vous pouvez utiliser au lieu de l'appelerrm
:Cette méthode gère des espaces bien.
Modifier, résout tout-en-un
Pour bash (depuis la version 4.0):
C'est tout.
La fuite d'extension ".ext" il y pour sélectionner des fichiers (ou répertoires) avec l'extension.
Option globstar active l' ** (recherche recursivelly).
Option nullglob supprime un * lorsqu'elle correspond à aucun fichier/dir.
Option dotglob inclut les fichiers qui commencent avec un point (fichiers cachés).
Attention, avant de bash 4.3,
**/
aussi traverse des liens symboliques vers des répertoires qui n'est pas souhaitable.La fonction suivante serait de parcourir récursivement tous les répertoires dans le
\home\ubuntu
directory( répertoire entier de la structure sous ubuntu ) et d'appliquer les contrôles nécessaires danselse
bloc.Il n'y a aucune raison pour canaliser la sortie de
find
dans un autre utilitaire.find
a un-delete
pavillon construit en elle.La pour les réponses fournies ne pas inclure des fichiers ou des répertoires qui commencent par un . le suivant a fonctionné pour moi:
Il suffit de ne
La suite de la boucle à travers le répertoire de façon récursive et la liste de tous les contenus :
for d in /home/ubuntu/*;
do
echo "listing contents of dir: $d";
ls -l $d/;
done
ls -l /home/ubuntu/*/
, donc c'est assez inutile.