Ускорить сценарий bash, запустив несколько экземпляров цикла for
У меня есть этот скрипт:
for i in `find ! -newermt "2016-02-13" -name "*svgz"`; do
inkscape --verb FitCanvasToDrawing --verb FileSave --verb FileClose ${i} --verb FileQuit
done
который ждет, пока inkscape завершит свою работу, а затем перезапустит его со следующим файлом. Я бы хотел, чтобы четыре экземпляра inkscape работали параллельно, чтобы ускорить процесс (у меня есть ~ 5000 файлов для обработки). Это возможно, и если да, то как? Заранее спасибо!
3 ответа
Попробуйте GNU Parallel.
sudo aptitude install parallel
Я не использовал его некоторое время, но его командная строка должна быть похожа на приведенную ниже:
find ! -newermt "2016-02-13" -name "*svgz" | \
parallel -j4 \
inkscape \
--verb FitCanvasToDrawing \
--verb FileSave \
--verb FileClose {} \
--verb FileQuit
где 4 - количество процессов, которые вы хотите запустить в любой момент времени.
Вы можете использовать GNU параллельно, как объяснялось здесь, для очень похожего вопроса, также включающего inkscape: https://stackoverflow.com/questions/26572397/how-to-process-20k-svg-files-with-inkscape-cli-mode-align-and-merge-objects
Еще один простой трюк, который я использовал сам недавно:
- Создайте сценарий "process.sh", обрабатывающий один файл, переданный ему в качестве аргумента.
Сохранить результат команды поиска в текстовом файле
Разбейте файл с помощью команды "split" на столько заданий, сколько вы хотите запустить параллельно.
Запустите несколько экземпляров process.sh, передав ему аргументы через сгенерированные файлы split и xargs.
Вот как я бы подошел к этому. Поскольку у меня нет одинаковых файлов, приведенный ниже пример кода призван открыть 4 текстовых файла с gedit
,
Как это работает? Ну, во-первых, мы находим файлы в жестко запрограммированном месте, где они могут храниться (FILEPATH
переменная). Затем мы передаем это while read
состав. Обратите внимание на использование -print0
а также IFS= read -d''
, Это очень часто встречается в программировании на bash для устранения проблемных имен файлов, которые содержат пробелы, непечатаемые символы и т. Д.
каждый gedit file &
звонки gedit
быть отсоединенным от сценария с &
, Это делает пока цикл продолжается без остановки.
То, что делает остановку цикла, является переменной COUNT. Как только мы посчитаем от 0 до некоторого числа, делимого на 4, MOD
переменная, которая вычисляется из оператора модуля, станет 0. Теперь оболочка будет ждать всплывающее окно (которое zenity
), чтобы подтвердить нерест еще 4 окна. Таким образом, мы считаем 4 раза, сбрасываем переменную, продолжаем.
Единственным недостатком здесь является то, что find
не сортирует файлы, поэтому они не обязательно будут в указанном порядке. Если порядок имеет значение, для кода потребуются дополнительные инструкции. В противном случае этого достаточно.
#!/bin/bash
FILEPATH="/home/xieerqi/MYTEXTFILES"
COUNT=0
find $FILEPATH -type f -name "*.txt" -print0 | \
while IFS= read -d '' FILE;
do
gedit $FILE &
COUNT=$(( $COUNT+1 ))
MOD=$(( $COUNT % 4 ))
if [ $MOD -eq 0 ]
then
zenity --question --text "Open 4 more files?" || exit
fi
done