Comment exécuter une commande sur plusieurs fichiers


13

C'est assez basique, j'ai un dossier avec plusieurs sous-dossiers de fichiers JS et je veux exécuter le compilateur Clojure de Google sur tous les fichiers de ces dossiers. La commande pour traiter un seul fichier est la suivante:

java -jar compiler.jar --js filename.js --js_output_file newfilename.js

Comment puis-je modifier cela pour qu'il s'exécute sur chaque fichier JS de ma structure de répertoires?

Réponses:


14

Vous pouvez utiliser find:

find . -name "*.js" -exec java -jar compiler.jar --js {} --js_output_file new{} \;

Merci, et je peux probablement en tirer parti pour tout renommer car les fichiers JS d'origine doivent être écrasés
— Mataniko

Dans le cas où --js et --js_output_file doivent différer, je ferais un script à deux lignes qui prend le nom de fichier comme paramètre, écrire la sortie dans un fichier temporaire et mvle fichier dans le nom d'origine.
— Anthon

Si vous voulez éviter de créer un script séparé, find -name '*.js' | while read jsfile; do java -jar compiler.jar --js "$jsfile" --js_output_file "new$jsfile" && mv "new$jsfile" "$jsfile"; donefaites l'affaire.
— David Baggerman

find -execest idéal pour les commandes simples. pour les plus complexes, find | xargsc'est beaucoup mieux et cela permet également d'exécuter des commandes en parallèle.
— rush

@rush explique peut-être pourquoi xargsc'est mieux?
— Mel Boyce

7

Vous pouvez également utiliser une forboucle simple , surtout si les fichiers se trouvent dans un seul répertoire (pas de sous-répertoires). Il peut également être modifié pour fonctionner avec des sous-répertoires.

Sans récursivité:

for filename in ./*.js
do
    java -jar compiler.jar --js "${filename}" --js_output_file "new${filename}"
done

ou comme doublure équivalente:

for filename in ./*.js; do java -jar compiler.jar --js "${filename}" --js_output_file "new${filename}"; done

Pour recurse dans des sous-répertoires (nécessite GNU bash 4.0 ou plus récent) (merci @ChrisDown ):

shopt -s globstar
for filename in ./**/*.js; do
    java -jar compiler.jar --js "${filename}" --js_output_file "new${filename}"
done

1
Cela ne recrée pas les sous-répertoires comme demandé dans la question. Avec bash4 +, vous pouvez le globstarfaire.
— Chris Down

1
Oui, c'est une bonne réponse et super à savoir, mais l'autre réponse fait exactement ce dont j'ai besoin.
— Mataniko

1
Ohh, j'ai réussi à manquer complètement la partie "plusieurs sous-dossiers". Désolé. Laissant la réponse dans un souci d'exhaustivité, cependant.
— un CVn le

3
@rush Puisque **peut correspondre à un niveau arbitraire de récursivité, **/*.jsfonctionne: sprunge.us/PXQK
— Chris Down

1
C'est généralement une bonne idée d'utiliser for f in ./*.js; doou for f in ./**/*.js; doafin de vous protéger des noms de fichiers commençant par un -(je ne sais pas si c'est nécessaire dans ce cas, mais c'est quand même une bonne habitude).
— evilsoup
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.