Выполнение команды для всех файлов в каталоге

Не мог бы кто-нибудь предоставить код, чтобы сделать следующее: Предположим, есть каталог файлов, каждый из которых нужно прогнать через программу. Программа выводит результаты в стандартный вывод. Мне нужен сценарий, который войдет в каталог, выполнит команду для каждого файла и объединит результаты в один большой выходной файл.

Например, чтобы выполнить команду для 1 файла:

$ cmd [option] [filename] > results.out
Комментарии к вопросу (2)
Решение

Следующий код bash передаст команде $file, где $file будет представлять каждый файл в /dir

for file in /dir/*
do
  cmd [option] "$file" >> results.out
done

Пример

el@defiant ~/foo $ touch foo.txt bar.txt baz.txt
el@defiant ~/foo $ for i in *.txt; do echo "hello $i"; done
hello bar.txt
hello baz.txt
hello foo.txt
Комментарии (8)

Как насчет этого:

find /some/directory -maxdepth 1 -type f -exec cmd option {} \; > results.out
  • Аргумент -maxdepth 1 предотвращает рекурсивный спуск find в любые вложенные каталоги. (Если вы хотите, чтобы такие вложенные каталоги обрабатывались, этот аргумент можно опустить).
  • -type -f указывает, что будут обрабатываться только простые файлы.
  • -exec cmd option {} указывает запустить cmd с указанной option для каждого найденного файла, при этом имя файла заменяется на {}.
  • \; обозначает конец команды.
  • Наконец, вывод всех отдельных запусков cmd перенаправляется в файл results.out

Однако, если вам важен порядок обработки файлов, лучше написать цикл. лучше написать цикл. Я думаю, что find обрабатывает файлы в порядке следования (хотя я могу ошибаться в этом), что может быть не тем, что что может быть не тем, что вам нужно.

Комментарии (5)

Я'м делаешь это на мой Raspberry Pi из командной строки с помощью команды:

for i in *;do omxplayer "$i";done
Комментарии (0)

Мне нужно скопировать все .MD файлы из одного каталога в другой, так вот что я сделал.

`ибо я в */.МД;делаем mkdir -Р ../документов/то" Я" и &&усилителя; РМ -Р ../документов/то" Я" и &&усилителя; КП " В$Я" и " по../документов/$я" и &АМП;& Эхо " Я -> ../документов/$я и решила попробовать сделать

Что довольно трудно читать, так что давайте разбить его вниз.

первый компакт-диск в каталог с файлами,

`ибо я в */.МД; для каждого файл в свой шаблон

`команды mkdir -Р купила ../документов/&;$я" и сделать этот каталог в папке Docs вне папку, содержащую файлы. Что создает дополнительную папку с именем этого файла.

РМ -Р ../документов/то" Я"в удалить лишнюю папку, которая была создана в результате команды mkdir -Р

КП " В$Я" и " от../документов/$я" в скопировать сам файл

Эхо " Я -> ../документов/$я" в Эхе, что ты сделал

сделали жить долго и счастливо

Комментарии (1)

Один быстрый и грязный способ, который получает работу иногда:

find directory/ | xargs  Command 

Например, чтобы найти количество строк во всех файлах в текущем каталоге, вы можете сделать:

find . | xargs wc -l
Комментарии (6)

Параметр maxdepth

Я нашел это хорошо работает с Джим Льюис'ы ответ Просто добавьте немного как это:

$ export DIR=/path/dir && cd $DIR && chmod -R +x *
$ find . -maxdepth 1 -type f -name '*.sh' -exec {} \; > results.out

Заказ# Сортировка

Если вы хотите выполнить сортировку, изменить ее так:

$ export DIR=/path/dir && cd $DIR && chmod -R +x *
find . -maxdepth 2 -type f -name '*.sh' | sort | bash > results.out

Просто для примера, это будет выполняться в следующем порядке:

bash: 1: ./assets/main.sh
bash: 2: ./builder/clean.sh
bash: 3: ./builder/concept/compose.sh
bash: 4: ./builder/concept/market.sh
bash: 5: ./builder/concept/services.sh
bash: 6: ./builder/curl.sh
bash: 7: ./builder/identity.sh
bash: 8: ./concept/compose.sh
bash: 9: ./concept/market.sh
bash: 10: ./concept/services.sh
bash: 11: ./product/compose.sh
bash: 12: ./product/market.sh
bash: 13: ./product/services.sh
bash: 14: ./xferlog.sh

Неограниченную Глубину

Если вы хотите исполнять на неограниченную глубину при определенных условиях, вы можете использовать это:

export DIR=/path/dir && cd $DIR && chmod -R +x *
find . -type f -name '*.sh' | sort | bash > results.out

затем положите сверху каждого файлы в каталогах, как ребенок:

#!/bin/bash
[[ "$(dirname `pwd`)" == $DIR ]] && echo "Executing `realpath $0`.." || return

и где-то в теле родительского файла:

if <a condition is matched>
then
    #execute child files
    export DIR=`pwd`
fi
Комментарии (0)

Принятых/высокого голосовал ответы замечательные, но им не хватает несколько мельчайшие детали. Это сообщение охватывает случаи о том, как лучше обрабатывать, когда корпус имени пути расширения (Глоб) в случае, когда имена файлов содержат встроенные переводы строк/символов тире и двигать команду вывода повторное направление выхода из цикла при записи результатов в файл.

При запуске оболочки Глоб расширения, используя * есть возможность для расширения с ошибкой, если есть но файлы в каталоге и ООН расширила Глоб строка будет передан команде должен быть запущен, Что может иметь нежелательные результаты. В Баш Shell предоставляет возможность расширенной оболочки для этого, используя nullglob. Так что цикл в основном будет следующим образом внутри директория, содержащая файлы

 shopt -s nullglob

 for file in ./*; do
     cmdToRun [option] -- "$file"
 done

Это позволит вам благополучно выйти из цикла, если выражение ./* возвращает любые файлы ( если каталог пуст)

или в POSIX-совместимой путь (nullglob это Баш конкретно)

 for file in ./*; do
     [ -f "$file" ] || continue
     cmdToRun [option] -- "$file"
 done

Это позволяет перейти внутри цикла, если выражение не раз и условие [ -ф " в файл$то" ] проверить, если ООН-расширить строку/. * является допустимым именем файла в этом каталоге, который бы'т быть. Так что на эту ошибку состояние, используя "продолжить" мы вернуться обратно в для петли, которая выиграла'т впоследствии работать.

Также обратите внимание на использование -- просто перед передачей аргумента имя файла. Это необходимо потому, что, как уже отмечалось, имена оболочка может содержать дефисы в любом месте в имени файла. Некоторые команды оболочки интерпретировать, что и относиться к ним как опция команды, когда имя не правильно процитировал и выполняет команды, думая, если флаг предоставляется.

В -- сигнализирует об окончании параметров командной строки в этом случае значит, команда должна'т разобрать все строки после этой точки, как флаги команды, но только как имена.


Дважды цитируя имена файлов правильно решает случаи, когда имена содержат символы Глоб или пробелы. Но *Никс имена также могут содержать переводы строк в них. Так что мы де-лимит файлов с Единственный персонаж, который не может быть частью действительного именем - нулевой байт (\0). Поскольку Баш внутренне использует `строки в стиле C, в которой нулевой байт используются для обозначения конца строки, это подходящий кандидат для этого.

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

( shopt -s nullglob; printf '%s\0' ./* ) | while read -rd '' file; do
    cmdToRun [option] -- "$file"
done

В nullglob и Е объять ( .. ), который означает, что они в основном работают в суб-оболочки (оболочки ребенка), потому что, чтобы избежать nullglob возможность отражать на материнской оболочки, после завершения команды. В-д ''впрочитатькоманда уступчивый _не_ в POSIX, так нужноБашShell для этого надо делать. Используянайти команду` это может быть сделано как


while IFS= read -r -d '' file; do
    cmdToRun [option] -- "$file"
done < 
Комментарии (0)

я думаю, что самое простое решение-это: ш /реж/* > ./result.txt

Комментарии (1)

Основываясь на подходе @Jim Lewis'a:

Вот быстрое решение с использованием find, а также сортировки файлов по дате модификации:

$ find  directory/ -maxdepth 1 -type f -print0 | \
  xargs -r0 stat -c "%y %n" | \
  sort | cut -d' ' -f4- | \
  xargs -d "\n" -I{} cmd -op1 {} 

Для сортировки см:

http://www.commandlinefu.com/commands/view/5720/find-files-and-list-them-sorted-by-modification-time

Комментарии (3)