cat a.txt | xargs -I % echo %
В приведенном выше примере xargs принимает echo %
в качестве аргумента команды. Но в некоторых случаях мне нужно несколько команд для обработки аргумента вместо одной. Например:
cat a.txt | xargs -I % {command1; command2; ... }
Но xargs не принимает эту форму. Одно из известных мне решений состоит в том, что я могу определить функцию для переноса команд, но это не конвейер, я не предпочитаю это. Есть ли другое решение?
while
который может содержать несколько команд.Ответы:
... или без бесполезного использования кошки :
Чтобы объяснить некоторые тонкости:
Использование
"$arg"
вместо%
(и отсутствие-I
вxargs
командной строке) по соображениям безопасности: передача данных вsh
список аргументов командной строки вместо их замены в коде предотвращает содержимое, которое могут содержать данные (например$(rm -rf ~)
, вредоносный пример) от выполнения в виде кода.Точно так же использование
-d $'\n'
- это расширение GNU, которое заставляетxargs
рассматривать каждую строку входного файла как отдельный элемент данных. Либо это, либо-0
(которое ожидает NUL вместо новых строк) необходимо, чтобы xargs не пытался применить подобный оболочке (но не полностью совместимый с оболочкой) синтаксический анализ для потока, который он читает. (Если у вас нет GNU xargs, вы можете использоватьtr '\n' '\0' <a.txt | xargs -0 ...
для чтения строк без него-d
).Это
_
заполнитель$0
, такой, что другие значения данных, добавленныеxargs
становлением$1
и вперед, который является набором значений по умолчанию, по которымfor
цикл повторяется.источник
sh -c
- обратите внимание, что точка с запятой после каждой команды не является обязательной, даже если это последняя команда в списке.command1
иcommand2
; Позже я понял, что они не нужны.}
:sh -c '{ command1; command2; }' -- but it's not required at the end of a command sequence that doesn't use braces:
sh -c 'command1; command2'`%
символ где-то в вашей передаваемой строкеsh -c
, то это подвержено уязвимостям безопасности: имя файла, содержащее$(rm -rf ~)'$(rm -rf ~)'
(и это вполне допустимая подстрока в имени файла в распространенных файловых системах UNIX!), Вызовет у кого-то очень плохой день ,С GNU Parallel вы можете делать:
Посмотрите вступительные видео, чтобы узнать больше: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
Из соображений безопасности рекомендуется использовать менеджер пакетов для установки. Но если вы не можете сделать это, вы можете использовать эту установку 10 секунд.
10-секундная установка попытается выполнить полную установку; в случае неудачи - личная установка; если это не удается, минимальная установка.
источник
Это просто еще один подход без xargs и cat:
источник
IFS
, он будет игнорировать начальные и конечные пробелы в именах файлов; если вы не добавите-r
, имена файлов с буквенными обратными слешами будут игнорироваться.xargs
. (Это трудно расширить, чтобы сделать что-то похожее на вариант GNUxargs
'-P<n>
)$ command | while read line; do c1 $line; c2 $line; done
Ты можешь использовать
{} = переменная для каждой строки в текстовом файле
источник
file.txt
содержит элемент данных$(rm -rf ~)
в качестве подстроки?Я добавляю в .bashrc / .profile эту функцию:
тогда вы можете делать такие вещи, как
который менее многословен, чем xargs или -exec. Вы также можете изменить функцию, чтобы вставить значение из чтения в произвольном месте команд в каждую, если вам нужно такое поведение.
источник
Я предпочитаю стиль, который позволяет режим пробега (без
| sh
):Работает с трубами тоже:
источник
-P
... (Если нет, я в основном использую-exec
onfind
, так как мои входные данные в основном являются именами файлов)Немного опоздал на вечеринку.
Я использую формат ниже для сжатия моих каталогов с тысячами крошечных файлов перед миграцией. Если вам не нужны одинарные кавычки внутри команд, это должно сработать.
С некоторой модификацией, я уверен, это будет кому-то полезно. Проверено в
Cygwin
(бабун)find .
Найти здесь-maxdepth 1
Не входите в дочерние каталоги! -path .
Исключить. / Путь к текущему каталогу-type d
соответствует только каталогам.-print0
Отдельный вывод нулевыми байтами \ 0.| xargs
Pipe to xargs.-0
Входные данные - разделенные нулем байты-I @@
. Замените @@ вводом.bash -c '...'
Выполнить команду Bash{...}
Группировка команд&&
Выполнить следующую команду, только если предыдущая команда успешно завершена (выход 0)Финал
;
важен, иначе он потерпит неудачу.Вывод:
Обновление за июль 2018 года:
Если вы любите хаки и играете, вот кое-что интересное:
Вывод:
Объяснение:
- Создайте сценарий с одним вкладышем и сохраните его в переменной
-
xargs
читаетa.txt
и выполняет его какbash
сценарий-
@@
проверяет каждый раз, когда передается вся строка- Установка
@@
после--
гарантирует, что@@
в качестве ввода позиционного параметра вbash
команду, а не вbash
началоOPTION
, т.е. как-c
само по себе, что означаетrun command
--
волшебный, он работает со многими другими вещами, т.е.ssh
дажеkubectl
источник
find . -type f -print0|xargs -r0 -n1 -P20 bash -c 'f="{}";ls -l "$f"; gzip -9 "$f"; ls -l "$f.gz"'
(Это немного легче при преобразовании циклов)"$@"
- единственный способ избежать этого ... (с помощью,-n1
если вы хотите ограничить количество параметров))--
используется оболочкой, чтобы сказать, что больше никаких вариантов не должно быть принято. Это позволяет быть-
после--
тоже. Вы можете получить очень интересный и запутанный результат, если вы этого не сделаете, например,grep -r
при включении в шаблон-
! То, как вы это произносите, не проясняет это, на самом деле не объясняет, как это работает. Iirc - это POSIX, но, в любом случае, на это стоит обратить внимание. Просто кое-что рассмотреть. И я люблю этот бонус, кстати!Это, кажется, самая безопасная версия.
(
-0
Могут быть удалены иtr
заменены редиректа (или файл может быть заменен нулем отделенный файл , а). В основном там , так как я в основном используютxargs
сfind
с-print0
выходом) (Это может также иметь значение вxargs
версиях без-0
расширения)Это безопасно, так как аргументы передают параметры в оболочку в виде массива при его выполнении. Оболочка (по крайней мере
bash
) затем передаст их как неизмененный массив другим процессам, когда все будут получены с использованием["$@"][1]
Если вы используете
...| xargs -r0 -I{} bash -c 'f="{}"; command "$f";' ''
, назначение не будет выполнено, если строка содержит двойные кавычки. Это верно для каждого варианта, использующего-i
или-I
. (Из-за того, что он заменяется на строку, вы всегда можете вводить команды, вставляя неожиданные символы (например, кавычки, обратные символы или знаки доллара) во входные данные)Если команды могут принимать только один параметр за раз:
Или с несколько меньшими процессами:
Если у вас есть GNU
xargs
или другой с-P
расширением, и вы хотите запустить 32 процесса параллельно, каждый с не более чем 10 параметрами для каждой команды:Это должно быть устойчиво к любым специальным символам на входе. (Если ввод разделен нулем.)
tr
Версия получит недопустимый ввод, если некоторые строки содержат символы новой строки, но это неизбежно при использовании файла, разделенного символом новой строки.Пустой первый параметр для
bash -c
связан с этим: (соbash
страницы руководства ) (спасибо @clacke)источник
"$@"
bash -c 'command1 "$@"; command2 "$@";' arbitrarytextgoeshere
bash
with-c
принимает сначала (после команд) один аргумент, который будет именем процесса, затем он принимает позиционные аргументы. Попробуйтеbash -c 'echo "$@" ' 1 2 3 4
и посмотрите, что получится.Другое возможное решение, которое работает для меня, это что-то вроде -
Обратите внимание на 'bash' в конце - я предполагаю, что он передается как argv [0] в bash. Без этого в этом синтаксисе первый параметр каждой команды теряется. Это может быть любое слово.
Пример:
источник
"$@"
, то вы разделяете строки и расширяете список аргументов.Мой текущий BKM для этого
К сожалению, это использует Perl, который менее вероятно будет установлен, чем Bash; но он обрабатывает больше ввода, чем принятый ответ. (Я приветствую вездесущую версию, которая не зависит от Perl.)
Предложение @ KeithThompson о
это здорово - если у вас нет символа комментария оболочки # на вашем входе, в этом случае часть первой команды и вся вторая команда будут усечены.
Хэши # могут быть довольно распространенными, если входные данные получены из списка файловых систем, таких как ls или find, и ваш редактор создает временные файлы с # в их имени.
Пример проблемы:
Ой, вот проблема:
Ааа, так лучше
источник
ls | xargs -I % sh -c 'echo 1 "%"; echo 2 "%"'