Как запустить команду для нескольких файлов


13

Это довольно просто, у меня есть папка с несколькими подпапками файлов JS, и я хочу запустить компилятор Google Clojure для всех файлов в этих папках. Команда для обработки одного файла выглядит следующим образом:

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

Как я могу изменить это для запуска на каждом файле JS в моей структуре каталогов?

Ответы:


14

Вы можете использовать find:

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

Спасибо, и я, вероятно, могу использовать это, чтобы переименовать все, потому что оригинальные файлы JS должны быть перезаписаны
Mataniko

В случае, если --js и --js_output_file должны различаться, я бы сделал двухстрочный скрипт, который принимает имя файла в качестве параметра, записывал вывод во временный файл, а mvфайл - в исходное имя.
Anthon

Если вы хотите избежать создания отдельного скрипта, find -name '*.js' | while read jsfile; do java -jar compiler.jar --js "$jsfile" --js_output_file "new$jsfile" && mv "new$jsfile" "$jsfile"; doneсделайте свое дело.
Дэвид Баггерман,

find -execотлично подходит для простых команд. для сложных find | xargsгораздо лучше, а также позволяет выполнять команды параллельно.
Раш

@ Может быть, объяснить, почему xargsлучше?
Мел Бойс,

7

Вы также можете использовать простой forцикл, особенно если файлы находятся в одном каталоге (без подкаталогов). Его также можно модифицировать для работы с подкаталогами.

Без рекурсии:

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

или в качестве эквивалентной однострочной:

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

Чтобы перейти в подкаталоги (требуется GNU bash 4.0 или новее) (спасибо @ChrisDown ):

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

1
Это не возвращает подкаталоги, как указано в вопросе. С bash4 +, вы можете использовать globstarдля этого.
Крис Даун

1
Да, это хороший ответ и приятно знать, но другой ответ делает именно то, что мне нужно.
Матанико

1
Ох, мне удалось полностью пропустить часть "несколько подпапок". Сожалею. Однако для полноты изложения оставим ответ.
CVn

3
@rush Так как **может соответствовать произвольному уровню рекурсии, **/*.jsработает: sprunge.us/PXQK
Крис Даун

1
Как правило, это хорошая идея, чтобы использовать for f in ./*.js; doили for f in ./**/*.js; doдля того, чтобы защитить себя от имен файлов, начинающихся с -(я не знаю, если это необходимо в этом случае, но это хорошая привычка в любом случае).
evilsoup
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.