Bagaimana cara menjalankan perintah pada banyak file

13

Ini cukup mendasar, saya memiliki folder dengan beberapa subfolder file JS dan saya ingin menjalankan kompiler Clojure Google pada semua file di folder tersebut. Perintah untuk memproses satu file adalah sebagai berikut:

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

Bagaimana cara memodifikasi ini untuk dijalankan pada setiap file JS dalam struktur direktori saya?

Mataniko
sumber

Jawaban:

14

Anda bisa menggunakan find:

find . -name "*.js" -exec java -jar compiler.jar --js {} --js_output_file new{} \;
Anthon
sumber
Terima kasih, dan saya mungkin dapat memanfaatkan ini untuk mengganti nama semuanya karena file JS asli perlu ditimpa
Mataniko
Jika --js dan --js_output_file perlu berbeda, saya akan membuat skrip dua baris yang menggunakan nama file sebagai parameter, menulis output ke file sementara dan mvfile ke nama asli.
Anthon
Jika Anda ingin menghindari membuat skrip terpisah, find -name '*.js' | while read jsfile; do java -jar compiler.jar --js "$jsfile" --js_output_file "new$jsfile" && mv "new$jsfile" "$jsfile"; donelakukan triknya.
David Baggerman
find -execsangat bagus untuk perintah sederhana. untuk yang kompleks find | xargsjauh lebih baik dan juga memungkinkan untuk menjalankan perintah secara paralel.
buru
@rush mungkin menjelaskan mengapa xargslebih baik?
Mel Boyce
7

Anda juga dapat menggunakan forloop sederhana , terutama jika file berada dalam satu direktori (tidak ada subdirektori). Itu dapat dimodifikasi untuk bekerja dengan subdirektori juga.

Tanpa rekursi:

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

atau sebagai satu-baris yang setara:

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

Untuk kembali ke subdirektori (memerlukan GNU bash 4.0 atau yang lebih baru) (terima kasih @ChrisDown ):

shopt -s globstar
for filename in ./**/*.js; do
    java -jar compiler.jar --js "${filename}" --js_output_file "new${filename}"
done
sebuah CVn
sumber
1
Ini tidak berulang subdirektori seperti yang ditanyakan dalam pertanyaan. Dengan bash4 +, Anda dapat menggunakannya globstaruntuk melakukannya.
Chris Down
1
Ya, itu jawaban yang bagus dan menyenangkan untuk diketahui, tetapi jawaban yang lain tepat seperti yang saya inginkan.
Mataniko
1
Ohh, saya berhasil melewatkan bagian "beberapa subfolder". Maaf. Meninggalkan jawaban di sekitar demi kelengkapan, meskipun.
CVn
3
@rush Karena **dapat menyamai tingkat rekursi yang berubah-ubah, **/*.jsberfungsi: sprunge.us/PXQK
Chris Down
1
Ini umumnya ide yang baik untuk digunakan for f in ./*.js; doatau for f in ./**/*.js; dountuk melindungi diri Anda dari nama file yang dimulai dengan -(Saya tidak tahu apakah itu perlu dalam kasus ini, tapi itu kebiasaan yang baik).
evilsoup