2010-12-10 20 views
3

Je souhaite écrire un script bash qui traite de manière récursive tous les fichiers d'un certain type.bash: traitement (récursif) de tous les fichiers d'un répertoire

Je sais que je peux obtenir la liste des fichiers correspondant en utilisant trouver ainsi:

trouver. -name « * .ext »

Je veux l'utiliser dans un script:

  1. liste récursive obatin des fichiers avec une extension donnée
  2. obtenir le chemin complet du fichier
  3. passer le chemin complet vers un autre script
  4. Vérifiez le code retour du script. Si ce n'est pas le cas, consignez le nom du fichier qui n'a pas pu être traité.

    ROOT_DIR = ~/work/projects 
    cd $ROOT_DIR 
    for f in `find . -name "*.ext"` 
    do 
        #need to lop off leading './' from filename, but I havent worked out how to use 
        #cut yet 
        newname = `echo $f | cut -c 3 
        filename = "$ROOT_DIR/$newname" 
    
        retcode = ./some_other_script $filename 
    
        if $retcode ne 0 
         logError("Failed to process file: $filename") 
    done 
    

    Ceci est ma première tentative d'écriture d'un script bash, alors l'extrait ci-dessus n'est pas susceptible de courir:

Mes premiers (pseudocode) comme celui-ci ressemble tentative. Heureusement, la logique de ce que j'essaie de faire est assez claire, et quelqu'un peut montrer comment joindre les points et convertir le pseudo-code ci-dessus en un script de travail.

Je suis en cours d'exécution sur Ubuntu

+1

Si vous utilisez « trouver $ ROOT_DIR -name "* .exe" 'vous n'aurez pas besoin de jouer avec le' ./ '. –

Répondre

12
find . -name '*.ext' \(-exec ./some_other_script "$PWD"/{} \; -o -print \) 
+0

+1 Bonne solution, je ne savais pas que vous pouviez utiliser -o de cette façon. Le seul problème est que parfois (pas ici) vous devez appeler une fonction au lieu d'un exécutable externe. – tokland

+0

Hmm assez cryptique cela .... (me rappelle Perl!). Je ne comprends pas ça. Comment le nom de fichier est-il transmis à l'autre script, et comment puis-je savoir si le script est retourné non nul, donc je sais faire quelque chose? – skyeagle

+1

@skyeagle: Le '{}' dans le prédicat '-exec' indique où injecter la correspondance actuelle. Le prédicat '-exec' lui-même teste le code résultat de la commande, en donnant vrai si 0, faux sinon. –

2

En utilisant | while read itérer sur les noms de fichiers est très bien tant qu'il n'y a pas de fichiers avec le retour de support à traiter:

find . -name '*.ext' | while IFS=$'\n' read -r FILE; do 
    process "$(readlink -f "$FILE")" || echo "error processing: $FILE" 
done 
+1

Je ne dirais pas que c'est officiellement découragé. C'est beaucoup mieux que 'for f dans $ (find)'. Il peut y avoir des problèmes s'il y a des espaces, des onglets ou des retours à la ligne dans les noms de fichiers. Il peut être amélioré comme ceci: 'alors que IFS = $ '\ n' lisez -r FILE' –

+0

@Dennis, je ne peux pas trouver la page en ce moment (peut-être pas officielle), mais il déconseillé d'utiliser" while | read "parce que Les retours de porteurs sont des caractères valides pour les fichiers (heureusement, personne ne les utilise). Ajouté votre suggestion – tokland

+0

De telles hypothèses sont toujours problématiques. Même si les utilisateurs «normaux» évitent souvent les nouvelles lignes dans les noms de fichiers, cela ne signifie pas que personne ne le fait - et un attaquant le fera certainement. Tout programme devrait essayer d'accepter tous les noms de fichiers autorisés; Heureusement, c'est très facile dans tous les langages de programmation, une autre raison d'éviter les scripts shell. – Philipp