Параметр `-J` для Xargs

Параметр `-J` для Xargs

Этот сайтпредоставляет xargsкоманде опцию -J, позволяющую передавать стандартный ввод в требуемую позицию в аргументе команды:

find . -name '*.ext' -print0 | xargs -J % -0 rsync -aP % user@host:dir/

но вСтраница руководства GNU xargsэта опция отсутствует.

Как это сделать, чтобы команды это принимали?

решение1

Я не уверен, что это то, чего вы ожидали, но в мире BSD (например, macOS) -Iи -Jотличается способ передачи нескольких "строк" команде. Пример:

$ ls
file1 file2 file3

$ find . -type f -print0 | xargs -I % rm %
rm file1
rm file2
rm file3

$ find . -type f -print0 | xargs -J % rm %
rm file1 file2 file3

Итак, с -I, xargs выполнит команду для каждого переданного ему элемента по отдельности. С -J, xargs выполнит команду один раз и объединит все элементы и передаст их в качестве аргументов все вместе.

Некоторые команды, такие как rmили mkdirмогут принимать несколько аргументов и действовать с ними так же, как если бы вы передали один аргумент и запустили их несколько раз. Но некоторые приложения могут меняться в зависимости от того, как вы передаете им аргументы. Например, tar. Вы можете создать файл tar, а затем добавить в него файлы или вы можете создать файл tar, добавив в него все файлы за один раз.

$ find . -iname "*.txt" -or -iname "*.pdf" -print0 | xargs -0 -J % tar cjvf documents.tar.bz2 %

решение2

Если это -Jфлаг для версии BSD, xargsя не думаю, что существует точный эквивалент для GNU xargs. -Jзаменяет одно вхождениеreplstr(например %) с каждой строкой, поступающей через стандартный ввод. Версия GNU имеетпохожийвариант, хотя: -I1. Однако, вы можете использоватьreplstrнесколько раз с этим флагом.

Для случаев использования, где неважно, есть ли один или несколько вызовов команд, вы должны иметь возможность использовать GNU xargs -Iв качестве замены. Но ваш пример использует rsync, и я уверен, что вы не хотите множественных вызовов этого.

Лучшим вариантом действий будет рассмотреть альтернативы, начинающиеся с findи действия -execor -execdir. Существует два варианта. Один из них аналогичен GNU, -Iа другой — BSD -J. Взгляните на эти примеры...

# Note the escaping of ';'
$ find /tmp -name '*.txt' -exec echo {} \;
/tmp/a.txt
/tmp/b.txt
..
/tmp/z.txt

А теперь сравните это с этим:

$ find /tmp -name '*.txt' -exec echo {} +
/tmp/a.txt /tmp/b.txt .. /tmp/z.txt

Единственное различие между ними заключается в том, какой «модификатор» стоит в конце, +или ;.

1 Еще больше сбивает с толку то, что версия BSD также имеет -Iи она похожа по функциям на обе версии -Jи GNU -I! Но на это -Iвлияют другие флаги и, скорее всего, это не то, что вы ищете.

Связанный контент