Этот сайтпредоставляет 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 имеетпохожийвариант, хотя: -I
1. Однако, вы можете использоватьreplstrнесколько раз с этим флагом.
Для случаев использования, где неважно, есть ли один или несколько вызовов команд, вы должны иметь возможность использовать GNU xargs -I
в качестве замены. Но ваш пример использует rsync
, и я уверен, что вы не хотите множественных вызовов этого.
Лучшим вариантом действий будет рассмотреть альтернативы, начинающиеся с find
и действия -exec
or -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
влияют другие флаги и, скорее всего, это не то, что вы ищете.