Как напечатать обработанный аргумент после каждого вызова команды с помощью xargs

Вопрос или проблема

Я запустил эту команду:

ls -1 | xargs -I% -n1 -P8 myprogramm -s1 -r5 -q -o %.dat %

Она выполняется с 8 запусками одновременно, переключатель -q в myprogramm отвечает за выход, так что это нормально.

Но я добавлю нечто вроде ; echo %, чтобы вывести имя файла на экран после завершения каждого запуска программы.

Я запустил эту команду:

ls -1 | xargs -I% -n1 -P8 myprogramm -s1 -r5 -q -o %.dat % ; echo %

Ошибок не наблюдаю, но вывод не соответствует тому, что я хотел.

После завершения всех запусков в bash я вижу только новую строку с одним символом, %.

Но я хочу получить вывод, как:

file1
file2
file3
...

% = fileN, является тем, что xargs запускает задания, как получить такой вывод?

Проверка интерпретирует ; как разделитель команд даже до выполнения xargs, поэтому сначала выполняется xargs, а потом запускается echo %.

Аргумент для xargs – это команда для выполнения, а не список команд. Если вам нужно выполнить несколько команд, запишите их в скрипт и запустите его из xargs.

Также разбор вывода ls в основном неверен. Он не работает корректно для имен файлов, содержащих пробелы.

Как насчет:

ls -1 | xargs -I% -n1 -P8 bash -c 'echo now run: "$@"; echo myprogramm -s1 -r5 -q -o "$@".dat "$@"' _ %

Пример:

$ touch {1..5}
$ ls -1 | xargs -I% -n1 -P8 bash -c 'echo now run: "$@"; echo myprogramm -s1 -r5 -q -o "$@".dat "$@"' _ %
now run: 1
myprogramm -s1 -r5 -q -o 1.dat 1
now run: 2
myprogramm -s1 -r5 -q -o 2.dat 2
now run: 4
myprogramm -s1 -r5 -q -o 4.dat 4
now run: 3
myprogramm -s1 -r5 -q -o 3.dat 3
now run: 5
myprogramm -s1 -r5 -q -o 5.dat 5

Также можно убрать %:

$ ls -1 | xargs  -n1 -P8 bash -c 'echo now run: "$@"; echo myprogramm -s1 -r5 -q -o "$@".dat  "$@"' _
now run: 1
myprogramm -s1 -r5 -q -o 1.dat 1
now run: 3
myprogramm -s1 -r5 -q -o 3.dat 3
now run: 4
myprogramm -s1 -r5 -q -o 4.dat 4
now run: 2
myprogramm -s1 -r5 -q -o 2.dat 2
now run: 5
myprogramm -s1 -r5 -q -o 5.dat 5

Уберите echo перед myprogramm, чтобы на самом деле запустить его.

Помните также:
Почему *не* разбирать `ls` (и что делать вместо этого)?.

Ответ или решение

Для решения задачи, обозначенной в вашем вопросе, давайте рассмотрим, как корректно использовать xargs для одновременного запуска нескольких команд, а также как выводить имя обрабатываемого аргумента после завершения каждой команды.

Ключевая проблема в вашем исходном коде заключается в том, что вы пытались использовать ; echo %, что не будет работать так, как вы ожидаете, поскольку ; разделяет команды, и echo выполняется сразу после xargs, не ожидая завершения процессов. Чтобы правильно отобразить имена файлов после выполнения каждой команды, необходимо использовать другую конструкцию.

Вот исправленный пример команды:

ls -1 | xargs -I% -n1 -P8 bash -c 'myprogramm -s1 -r5 -q -o "%.dat" "%"; echo "Обработка завершена для файла: %"' _ %

Объяснение:

  1. ls -1: Эта команда создаст список файлов в текущем каталоге, каждый файл будет на новой строке.

  2. xargs -I% -n1 -P8: Здесь мы используем xargs с опцией -I%, чтобы указать подстановочный символ %, который будет заменен на каждую строку (имя файла) из входного потока. Опция -n1 говорит о том, что один аргумент передается в каждую команду, а -P8 указывает, что одновременно могут выполняться 8 процессов.

  3. bash -c: Мы вызываем новый экземпляр оболочки bash, чтобы выполнить последовательность команд.

  4. myprogramm -s1 -r5 -q -o "%.dat" "%": Здесь вы выполняете вашу программу myprogramm, передавая необходимые параметры. Вместо % в имя выходного файла подставляется имя текущего файла, обрабатываемого в данный момент.

  5. echo "Обработка завершена для файла: %": После завершения выполнения команды выводится сообщение с информацией о том, какой файл был обработан, используя тот же подстановочный символ %.

Учтите:

  • Избегайте парсинга вывода ls, особенно если имена файлов могут содержать пробелы или специальные символы. Вместо этого, по возможности, используйте его в сочетании с find для обработки сложных имен файлов.

Пример:

Предположим, что у вас есть 5 файлов:

$ touch file1 file2 file3 file4 file5
$ ls -1 | xargs -I% -n1 -P8 bash -c 'myprogramm -s1 -r5 -q -o "%.dat" "%"; echo "Обработка завершена для файла: %"' _ %

Вывод будет примерно следующим:

Обработка завершена для файла: file1
Обработка завершена для файла: file2
...

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

Оцените материал
Добавить комментарий

Капча загружается...