Я знаю, что, учитывая l="a b c"
,
echo $l | xargs ls
доходность
ls a b c
Какая конструкция дает
mycommand -f a -f b -f c
Я знаю, что, учитывая l="a b c"
,
echo $l | xargs ls
доходность
ls a b c
Какая конструкция дает
mycommand -f a -f b -f c
Ответы:
Один из способов сделать это:
echo "a b c" | xargs printf -- '-f %s\n' | xargs mycommand
Это предполагает a
, b
и c
не содержат пробелы, переводы строк, кавычки или слэш. :)
С GNU findutil
вы можете справиться с общим случаем, но это немного сложнее:
echo -n "a|b|c" | tr \| \\0 | xargs -0 printf -- '-f\0%s\0' | xargs -0 mycommand
Вы можете заменить |
разделитель с каким - либо другим символом, который не появляется в a
, b
или c
.
Редактировать: как отмечает @MichaelMol , с очень длинным списком аргументов существует риск переполнения максимальной длины аргументов, которые могут быть переданы mycommand
. Когда это произойдет, последний xargs
разделит список и запустит еще одну копию mycommand
, и есть риск, что он останется неопределенным -f
. Если вы беспокоитесь об этой ситуации, вы можете заменить последнее xargs -0
выше чем-то вроде этого:
... | xargs -x -0 mycommand
Это не решит проблему, но прервет работу, mycommand
когда список аргументов станет слишком длинным.
mycommand
. Вы всегда можете добавить -x
к последнему xargs
.
xargs
вообще, а просто использовать, find
если оно может быть использовано. Это решение опасно; Вы должны по крайней мере предупредить о случае отказа в своем ответе.
find
было бы лучше общее решение, особенно когда начальные аргументы не являются именами файлов. :)
-f
и с примером инструмента, ls
используемого для иллюстрации, @ not-a-user имеет дело с именами файлов. И учитывая find
предлагает -exec
аргумент, который позволяет вам создавать командную строку, это нормально. (Пока mycommand
разрешено выполнять более одного раза. Если это не так, у нас есть еще одна проблема с использованием xargs
здесь ...)
Лучший способ решить эту проблему (ИМО) будет:
в zsh
:
l=(a b c)
mycommand -f$^l
или используя zip-массив, чтобы аргумент не был прикреплен к опции:
l=(a b c) o=(-f)
mycommand "${o:^^l}"
Таким образом, это все еще работает, если l
массив содержит пустые элементы или элементы, содержащие пробелы или любой другой проблемный символ для xargs
. Пример:
$ l=(a '' '"' 'x y' c) o=(-f)
$ printf '<%s>\n' "${o:^^l}"
<-f>
<a>
<-f>
<>
<-f>
<">
<-f>
<x y>
<-f>
<c>
в rc
:
l=(a b c)
mycommand -f$l
в fish
:
set l a b c
mycommand -f$l
(AFAIK, rc
и не fish
имеют архива массива)
С подобными Bourne-подобными оболочками в старом стиле bash
вы всегда можете это сделать (по-прежнему допуская любой символ в элементах $@
массива):
set -- a b c
for i do set -- "$@" -f "$i"; shift; done
mycommand "$@"
for i; do args+=('-f' "$i");done;
mycommand "${args[@]}"
, IDK, если это быстрее, но добавление 2 элементов в массив выглядит так, как будто это должно быть O (n), в то время как ваш set
цикл, вероятно, копирует и повторно анализирует накопленный список аргументов каждый раз (O (n ^ 2)).
ARG_MAX
и получить-f
отдельный от своего парного параметра риск .