Wiem to, biorąc pod uwagę l="a b c"
,
echo $l | xargs ls
daje
ls a b c
Który konstrukt daje
mycommand -f a -f b -f c
Wiem to, biorąc pod uwagę l="a b c"
,
echo $l | xargs ls
daje
ls a b c
Który konstrukt daje
mycommand -f a -f b -f c
Odpowiedzi:
Jednym ze sposobów na to:
echo "a b c" | xargs printf -- '-f %s\n' | xargs mycommand
Zakłada się a
, b
i c
nie zawiera spacji, znaków nowej linii, cytatów ani ukośników odwrotnych. :)
Z GNU findutil
możesz poradzić sobie z ogólnym przypadkiem, ale jest to nieco bardziej skomplikowane:
echo -n "a|b|c" | tr \| \\0 | xargs -0 printf -- '-f\0%s\0' | xargs -0 mycommand
Można wymienić |
separator z jakimś innym charakterze, że nie pojawi się a
, b
lub c
.
Edycja: Jak zauważa @MichaelMol , przy bardzo długiej liście argumentów istnieje ryzyko przepełnienia maksymalnej długości argumentów, które można przekazać mycommand
. Kiedy tak się stanie, ostatni xargs
podzieli listę i uruchomi kolejną kopię mycommand
, i istnieje ryzyko, że pozostanie ona nieskończona -f
. Jeśli martwisz się tą sytuacją, możesz zastąpić ostatnią z xargs -0
powyższych przez coś takiego:
... | xargs -x -0 mycommand
To nie rozwiąże problemu, ale przerwie działanie, mycommand
gdy lista argumentów będzie zbyt długa.
mycommand
. Zawsze możesz dodać -x
do ostatniego xargs
.
xargs
, a po prostu użyj, find
jeśli można go użyć. To rozwiązanie jest niebezpieczne; powinieneś przynajmniej ostrzec przypadek niepowodzenia w swojej odpowiedzi.
find
byłoby lepszym ogólnym rozwiązaniem, zwłaszcza gdy początkowe argumenty nie są nazwami plików. :)
-f
i przykładowym narzędziem ls
używanym do ilustracji @ not-a-user zajmuje się nazwami plików. I biorąc pod uwagę find
oferuje -exec
argument, który pozwala zbudować wiersz poleceń, jest w porządku. (Tak długo, jak mycommand
jest to dozwolone, aby wykonać więcej niż jeden raz. Jeśli tak nie jest, mamy kolejny problem z użyciem xargs
tutaj ...)
Lepszym sposobem rozwiązania tego problemu (IMO) byłoby:
w zsh
:
l=(a b c)
mycommand -f$^l
lub za pomocą kompresji tablicy, aby argument nie był dołączony do opcji:
l=(a b c) o=(-f)
mycommand "${o:^^l}"
W ten sposób nadal działa, jeśli l
tablica zawiera puste elementy lub elementy zawierające spacje lub inny problematyczny znak xargs
. Przykład:
$ l=(a '' '"' 'x y' c) o=(-f)
$ printf '<%s>\n' "${o:^^l}"
<-f>
<a>
<-f>
<>
<-f>
<">
<-f>
<x y>
<-f>
<c>
w rc
:
l=(a b c)
mycommand -f$l
w fish
:
set l a b c
mycommand -f$l
(AFAIK rc
i fish
nie ma zipowania tablicy)
Dzięki starym powłokom podobnym do Bourne'a bash
, zawsze możesz to zrobić (nadal dopuszczając dowolny znak w elementach $@
tablicy):
set -- a b c
for i do set -- "$@" -f "$i"; shift; done
mycommand "$@"
for i; do args+=('-f' "$i");done;
mycommand "${args[@]}"
. IDK, jeśli jest to szybsze, ale dodanie 2 elementów do tablicy wydaje się, że powinno to być O (n), podczas gdy twoja set
pętla prawdopodobnie kopiuje i ponownie analizuje zgromadzoną listę arg za każdym razem (O (n ^ 2)).
ARG_MAX
i-f
oddzielenie od sparowanego parametru.