Использование xargs для запуска скриптов bash в нескольких списках ввода с аргументами - PullRequest
0 голосов
/ 20 февраля 2019

Я пытаюсь запустить сценарий для нескольких списков файлов, параллельно передавая аргументы.У меня есть file_list1.dat, file_list2.dat, file_list3.dat.Я хотел бы запустить скрипт script.sh, который принимает 3 аргумента: arg1, arg2, arg3.

Для одного запуска я бы сделал:

sh script.sh file_list1.dat $arg1 $arg2 $arg3

Я хотел бы запустить эту команду впараллельно для всех списков файлов.

Моя попытка:

Ncores=4
ls file_list*.dat | xargs -P "$Ncores" -n 1 [sh script.sh [$arg1 $arg2 $arg3]]

Это приводит к ошибке: недопустимый номер для опции -P.Я думаю, что порядок этой команды неправильный.

Моя вторая попытка:

echo $arg1 $arg2 $arg3 | xargs ls file_list*.dat | xargs -P "$Ncores" -n 1 sh script.sh

Но это приводит к ошибке: xargs: ls: прекращено сигналом 13

Любые идеи о том, каков правильный синтаксис для передачи аргументов скрипту bash с xargs?

1 Ответ

0 голосов
/ 20 февраля 2019

Я не уверен, что точно понимаю, что вы хотите сделать.Это чтобы выполнить что-то вроде этих команд, но параллельно?

sh script.sh $arg1 $arg2 $arg3 file_list1.dat
sh script.sh $arg1 $arg2 $arg3 file_list2.dat
sh script.sh $arg1 $arg2 $arg3 file_list3.dat
...etc

Если это правильно, это должно работать:

Ncores=4
printf '%s\0' file_list*.dat | xargs -0 -P "$Ncores" -n 1 sh script.sh "$arg1" "$arg2" "$arg3"

Две основные проблемы в вашей версии заключались в том, что вы былипередача «Ncores» в виде литеральной строки (вместо использования $Ncores для получения значения переменной), и что у вас было [ ] вокруг команды и аргументов (что просто не является частью синтаксиса оболочки).Я также добавил двойные кавычки вокруг всех ссылок на переменные (обычно это хорошая практика) и использовал printf '%s\0'xargs -0) вместо ls.

Почему я использовал printf вместо ls?Потому что ls здесь не делает ничего полезного, что printf или echo или что-то еще не могло бы быть так же хорошо.Вы можете думать о ls как о средстве получения списков имен файлов, но в этом случае подстановочное выражение file_list*.dat расширяется до списка файлов до , когда команда запускается;все, что ls будет делать с ними, это посмотреть на каждого, сказать «да, это файл» самому себе, а затем распечатать его.echo может сделать то же самое с меньшими накладными расходами.Но с ls или echo вывод может быть неоднозначным, если любое имя файла содержит пробелы, кавычки или другие забавные символы.Некоторые версии ls пытаются «исправить» это, добавляя кавычки или что-то вокруг имен файлов с забавными символами, но это может совпадать или не совпадать с тем, как xargs анализирует ввод (если это вообще происходит).

Но printf '%s\0' является однозначным и предсказуемым - он печатает каждую строку (в данном случае имя файла) с последующим символом NULL, и это именно то, что xargs -0 принимает в качестве входных данных, поэтому нет никакой путаницыили неправильный анализ.

Ну, хорошо, есть один крайний случай: если нет подходящих файлов, шаблон с подстановочными знаками будет просто пропущен буквально, и он попытается запустить скрипт снерасширенная строка "file_list * .dat" в качестве аргумента.Если вы хотите избежать этого, используйте shopt -s nullglob перед этой командой (и shopt -u nullglob после, чтобы вернуться в нормальный режим).

О, и еще одна вещь: sh script.sh не самая лучшаяспособ запуска скриптов.Дайте сценарию правильную строку shebang в начале (#!/bin/sh, если он использует только базовые функции оболочки, #!/bin/bash или #!/usr/bin/env bash, если он использует bashisms ), и запустите его с ./script.sh.

...