Jak uruchomić polecenie na wielu plikach

13

Jest to dość proste, mam folder z kilkoma podfolderami plików JS i chcę uruchomić kompilator Clojure Google na wszystkich plikach w tych folderach. Polecenie przetworzenia pojedynczego pliku jest następujące:

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

Jak zmodyfikować to, aby działało na każdym pliku JS w mojej strukturze katalogów?

Mataniko
źródło

Odpowiedzi:

14

Możesz użyć find:

find . -name "*.js" -exec java -jar compiler.jar --js {} --js_output_file new{} \;
Anthon
źródło
Dzięki i prawdopodobnie mogę to wykorzystać, aby zmienić nazwę wszystkiego, ponieważ oryginalne pliki JS muszą zostać zastąpione
Mataniko
W przypadku, gdy pliki --js i --js_output_file muszą się różnić, stworzyłbym dwuwierszowy skrypt, który przyjmuje nazwę pliku jako parametr, zapisuje dane wyjściowe do pliku tymczasowego, a mvplik do oryginalnej nazwy.
Anthon
Jeśli chcesz uniknąć tworzenia osobnego skryptu find -name '*.js' | while read jsfile; do java -jar compiler.jar --js "$jsfile" --js_output_file "new$jsfile" && mv "new$jsfile" "$jsfile"; done, załatw sprawę.
David Baggerman
find -execdoskonale nadaje się do prostych poleceń. dla złożonych find | xargsjest znacznie lepszy, a także pozwala na równoległe uruchamianie poleceń.
pędzi
@ pośpiech może wyjaśnić, dlaczego xargsjest lepszy?
Mel Boyce
7

Możesz także użyć prostej forpętli, szczególnie jeśli pliki znajdują się w jednym katalogu (bez podkatalogów). Można go zmodyfikować, aby działał również z podkatalogami.

Bez rekurencji:

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

lub jako równoważny jednowarstwowy:

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

Aby przejść do podkatalogów (wymaga GNU bash 4.0 lub nowszej wersji) (dzięki @ChrisDown ):

shopt -s globstar
for filename in ./**/*.js; do
    java -jar compiler.jar --js "${filename}" --js_output_file "new${filename}"
done
CVn
źródło
1
Nie rekursuje podkatalogów, jak zadano w pytaniu. W bash4 + możesz globstarto zrobić.
Chris Down
1
Tak, to dobra odpowiedź i dobrze wiedzieć, ale druga odpowiedź robi dokładnie to, czego potrzebuję.
Mataniko
1
Och, udało mi się całkowicie przeoczyć część „kilka podfolderów”. Przepraszam. Pozostawiając jednak odpowiedź ze względu na kompletność.
CVn
3
@rush Ponieważ **może pasować do dowolnego poziomu rekurencji, **/*.jsdziała: sprunge.us/PXQK
Chris Down
1
Zasadniczo warto używać for f in ./*.js; dolub for f in ./**/*.js; dow celu ochrony przed nazwami plików zaczynającymi się od -(nie wiem, czy jest to konieczne w tym przypadku, ale i tak jest to dobry nawyk).
evilsoup