J'ai besoin de parcourir un répertoire de manière récursive et de supprimer tous les fichiers avec l'extension .pdf
et .doc
. Je parviens à parcourir un répertoire de manière récursive mais je ne parviens pas à filtrer les fichiers avec les extensions de fichiers mentionnées ci-dessus.
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 compléter le code, car je ne vais nulle part.
rm
fait partie du code d'OP, mais ce n'est pas vraiment pertinent pour la question posée. Je pense que ce serait plus sûr si les réponses étaient formulées en utilisant une commande inoffensive commeecho
.Réponses:
find
est juste fait pour ça.la source
-delete
option.find ... -print0 | xargs -0 ...
, pas raw find | xargs pour éviter les problèmes avec les noms de fichiers contenant des nouvelles lignes.xargs
sans option est presque toujours un mauvais conseil et ce n'est pas une exception. Utilisezfind … -exec
plutôt.Pour faire suite à la réponse de mouviciel, vous pouvez également le faire comme une boucle for, au lieu d'utiliser xargs. Je trouve souvent les xargs encombrants, surtout si je dois faire quelque chose de plus compliqué à chaque itération.
Comme un certain nombre de personnes l'ont commenté, cela échouera s'il y a des espaces dans les noms de fichiers. Vous pouvez contourner ce problème en définissant temporairement l'IFS (séparateur de champ interne) sur le caractère de nouvelle ligne. Cela échoue également s'il y a des caractères génériques
\[?*
dans les noms de fichier. Vous pouvez contourner ce problème en désactivant temporairement l'expansion des caractères génériques (globbing).Si vous avez des nouvelles lignes dans vos noms de fichiers, cela ne fonctionnera pas non plus. Vous êtes mieux avec une solution basée sur xargs:
(Les crochets échappés sont obligatoires ici pour que les
-print0
deuxor
clauses s'appliquent .)GNU et * BSD find ont également une
-delete
action, qui ressemblerait à ceci:la source
for f in $(find ...)
. N'utilisez pas cette méthode.Sans
find
:/tmp/*
sont des fichiers dans dir et/tmp/**/*
sont des fichiers dans des sous-dossiers. Il est possible que vous deviez activer l'option globstar (shopt -s globstar
). Donc, pour la question, le code devrait ressembler à ceci:Notez que cela nécessite bash ≥4.0 (ou zsh sans
shopt -s globstar
, ou ksh avecset -o globstar
au lieu deshopt -s globstar
). De plus, dans bash <4.3, cela traverse des liens symboliques vers des répertoires ainsi que des répertoires, ce qui n'est généralement pas souhaitable.la source
for f in /tmp/**
suffira. Inclut les fichiers de / tmp dir.for f in /tmp/*.{pdf,doc} tmp/**/*.{,pdf,doc} ; do
**
est une belle extension mais pas portable sur POSIXsh
. (Cette question est étiquetée bash mais ce serait bien de souligner que contrairement à plusieurs des solutions ici, il s'agit vraiment uniquement de Bash. Ou bien, cela fonctionne également dans plusieurs autres shells étendus.)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 en utilisant des piles et ainsi de suite, mais bon).
Cela dit,
find
c'est probablement un meilleur choix comme cela a déjà été suggéré.la source
Voici un exemple utilisant shell (
bash
):la source
Cela ne répond pas directement à votre question, mais vous pouvez résoudre votre problème avec un one-liner:
Certaines versions de find (GNU, BSD) ont une
-delete
action que vous pouvez utiliser au lieu d'appelerrm
:la source
Cette méthode gère bien les espaces.
Modifier, corrige un par un
la source
Pour bash (depuis la version 4.0):
C'est tout.
L'extension de fin ".ext" permet de sélectionner les fichiers (ou répertoires) avec cette extension.
L'option globstar active le ** (recherche récursive).
L'option nullglob supprime un * lorsqu'il ne correspond à aucun fichier / répertoire.
L'option dotglob inclut les fichiers commençant par un point (fichiers cachés).
Attention, avant bash 4.3,
**/
il traverse également des liens symboliques vers des répertoires, ce qui n'est pas souhaitable.la source
La fonction suivante itérerait récursivement dans tous les répertoires du
\home\ubuntu
répertoire (structure de répertoires entière sous ubuntu) et appliquerait les vérifications nécessaires enelse
bloc.la source
C'est la façon la plus simple que je connaisse de faire ceci:
rm **/@(*.doc|*.pdf)
**
rend ce travail récursif@(*.doc|*.pdf)
recherche un fichier se terminant par pdf OU docFacile à tester en toute sécurité en le remplaçant
rm
parls
la source
Il n'y a aucune raison de diriger la sortie de
find
vers un autre utilitaire.find
a un-delete
drapeau intégré.la source
Les autres réponses fournies n'incluront pas les fichiers ou répertoires commençant par un. ce qui suit a fonctionné pour moi:
la source
Fais juste
la source
Ce qui suit va parcourir le répertoire donné de manière récursive et lister tout le contenu:
for d in /home/ubuntu/*; do echo "listing contents of dir: $d"; ls -l $d/; done
la source
ls -l /home/ubuntu/*/
, donc c'est assez inutile.Si vous pouvez modifier le shell utilisé pour exécuter la commande, vous pouvez utiliser ZSH pour effectuer le travail.
Cela fera une boucle récursive dans tous les fichiers / dossiers.
la source