Вопрос или проблема
Я хочу запустить команду N раз параллельно, используя bash и xargs на системе Linux. Команда выглядит так:
for i in `seq 1 $(howmany.txt)`; do aprogramm --file file$i.dat ; done
Файл howmany.txt
содержит значение 100
, а ntimes.txt
содержит значение 5
.
Файлы file1
до file100
существуют, последовательно от 1 до 100, и я хочу обрабатывать их по 5 раз параллельно. Как я могу сделать это с помощью xargs
?
Вместо того чтобы писать сценарий для выполнения команд, напишите сценарий, который выводит команды:
for i in `seq 1 $(howmany.txt)`
do echo "aprogramm --file file$i.dat"
done
Каждая строка этого вывода должна быть корректным синтаксисом команды для выбранного вами интерпретатора команд.
Как только вывод будет выглядеть хорошо, передайте его в parallel(1) с опцией -j5
, чтобы запустить 5 заданий параллельно:
for i in `seq 1 $(howmany.txt)`
do echo "aprogramm --file file$i.dat"
done | parallel -j5
В показанном вами коде есть несколько проблем. Во-первых, $(howmany.txt)
будет пытаться выполнить howmany.txt
. Если это исполняемый сценарий, находящийся в вашем PATH, который выводит число, тогда это может сработать, но если это просто текстовый файл с числом, вам нужно использовать $(cat howmany.txt)
. Во-вторых, лучше использовать $( command )
вместо `seq`
для большей ясности и возможности вложения команд.
С учетом этого, чтобы сделать это с помощью xargs
, вам нужно что-то вроде:
seq 1 $(< howmany.txt) | xargs -I {} -n1 -P $(< ntimes.txt) aprogramm --file file{}.dat
На самом деле, это работа для GNU parallel:
parallel -j ntimes.txt aprogramm --file file{} < howmany.txt
Или, если все ваши файлы называются fileN
и вы хотите обработать все fileN
(так что вам на самом деле не нужен howmany.txt
), то вы можете сделать:
parallel -j ntimes.txt aprogramm --file {} ::: file*
Одно из многих преимуществ parallel
перед xargs
заключается в том, что вы можете изменить число в howmany.txt
во время выполнения, чтобы увеличить или уменьшить количество работающих заданий.
Для обработки файлов пакетами используйте xargs -n
. Если в пакет обрабатывается один файл, используйте 1:
echo file*.dat | xargs -n1
Чтобы обрабатывать их параллельно, используйте -P
.
echo file*.dat | xargs -n1 -P$(< ntimes.txt) aprogramm --file
Предположения:
- файлы
howmany.txt
иntimes.txt
гарантированно содержат одно целое число и ничего больше - в каталоге могут быть другие файлы, которые мы не хотим обрабатывать (например, простой
find . -name 'file*.dat'
может вернуть больше файлов, чем необходимо)
Для демонстрационных целей:
$ cat aprogram
#!/bin/bash
echo "input: $@"
sleep 3
$ cat howmany.txt
10
$ cat ntimes.txt
4
Одна идея с использованием метода Джима для вывода списка имен файлов, переданных в xargs:
read -r max < howmany.txt
read -r count < ntimes.txt
for ((i=1; i<=max; i++))
do
echo "file$i.dat"
done | xargs -r -n1 -P "$count" ./aprogram --file
Это генерирует:
input: --file file1.dat # 4 вызова подряд
input: --file file2.dat
input: --file file3.dat
input: --file file4.dat
# 3 сек задержки
input: --file file5.dat # 4 вызова подряд
input: --file file6.dat
input: --file file7.dat
input: --file file8.dat
# 3 сек задержки
input: --file file9.dat # последние 2 вызова подряд
input: --file file10.dat
# 3 сек задержки
Ответ или решение
Конечно! Давайте детально разберем, как вы можете обрабатывать файлы с использованием команды xargs
и запустить команду N раз параллельно в Bash на системе Linux.
Исходные данные
У вас есть файл howmany.txt
, который содержит число 100, и файл ntimes.txt
, содержащий число 5. Вы хотите выполнить команду aprogramm --file file{i}.dat
для каждой из файлов от file1.dat
до file100.dat
, обрабатывая 5 файлов одновременно.
Шаги для решения задачи
-
Обработка содержимого файлов:
Вам нужно сначала считать количество файлов для обработки и количество параллельных процессов из указанных текстовых файлов. Это можно сделать с помощью командыread
. -
Генерация списка файлов:
Для создания списка файлов в форматеfile{i}.dat
, гдеi
— это число от 1 до 100, можно использовать цикл. -
Использование xargs:
Мы будем использоватьxargs
для запуска вашей программы одновременно для N файлов.
Пример скрипта
Вот пример Bash-скрипта, который решает вашу задачу:
#!/bin/bash
# Читаем значения из файлов
read -r max < howmany.txt
read -r count < ntimes.txt
# Генерируем список файлов и передаем в xargs
for ((i=1; i<=max; i++))
do
echo "file$i.dat"
done | xargs -r -n1 -P "$count" aprogramm --file
Объяснение кода
-
Чтение значений:
read -r max < howmany.txt
: считывает максимальное число файлов.read -r count < ntimes.txt
: считывает количество параллельных процессов.
-
Генерация списка:
- С помощью цикла
for
мы генерируем имена файлов отfile1.dat
доfile100.dat
и передаем их в стандартный вывод.
- С помощью цикла
-
Параллельное выполнение команды:
- Используя
xargs
с флагом-n1
, мы говоримxargs
обрабатывать по одному элементу за раз. - Флаг
-P "$count"
указывает количество параллельных процессов, которое мы считаем из файлаntimes.txt
. aprogramm --file
— это команда, которую мы хотим выполнить для каждого сгенерированного имени файла.
- Используя
Дополнительные рекомендации
- Убедитесь, что скрипт
aprogramm
существует и имеет права на выполнение. - Запустите скрипт в соответствующей директории, где находятся файлы, чтобы получить правильные результаты.
- Поскольку
xargs
будет работать параллельно, вы можете увидеть одновременное выполнение команд, что может помочь сократить общее время обработки.
Таким образом, вы сможете эффективно обрабатывать файлы несколько раз параллельно, используя Bash и xargs
. Если у вас возникнут дополнительные вопросы или понадобится помощь в настройки вашего скрипта, не стесняйтесь спрашивать!