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?

Jawaban:


14

Anda bisa menggunakan find:

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

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

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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.