xargs-在每个参数后附加一个参数


12

我知道,因为l="a b c"

echo $l | xargs ls

产量

ls a b c

哪个结构产生

mycommand -f a -f b -f c

Answers:


13

一种方法是:

echo "a b c" | xargs printf -- '-f %s\n' | xargs mycommand

假定为ab并且c不包含空格,换行符,引号或反斜杠。:)

使用GNU,findutil您可以处理一般情况,但是稍微复杂一些:

echo -n "a|b|c" | tr \| \\0 | xargs -0 printf -- '-f\0%s\0' | xargs -0 mycommand

您可以取代|一些其他字符分隔符,没有出现在abc

编辑:正如@MichaelMol所指出的那样,由于参数的列表很长,有可能溢出可传递给的参数的最大长度mycommand。发生这种情况时,最后一个xargs将拆分列表并运行的另一个副本mycommand,因此存在未终止的风险-f。如果您担心这种情况,可以用以下xargs -0类似的内容代替上面的内容:

... | xargs -x -0 mycommand

这不能解决问题,但是mycommand当参数列表过长时,它将中止运行。


1
您有一个非常丑陋的风险,那就是超过其配对参数ARG_MAX-f使其与之分开。
Michael Mol's

@MichaelMol这是一个很好的观点,但是我认为在不了解更多信息的情况下,没有任何有意义的方式来处理这种情况mycommand。您可以随时添加-x到最后一个xargs
聪桂

我认为适当的解决方案可能根本不使用xargs,并且只要find可以使用就使用。这种解决方案很危险;您至少应在回答中警告失败案例。
Michael Mol's

@MichaelMol我真的不知道怎么find会有更好的通用解决方案,尤其是当初始参数不是文件名时。:)
佐藤桂

我们不知道初始参数是什么。我们仅看到给出的示例,而没有看到启发该问题的场景。直觉表明,使用一个名为的参数-f和一个ls用于说明的示例工具,@ not-a-user处理文件名。给定find提供了-exec参数,它允许您构造命令行,这很好。(只要mycommand允许执行多次即可。如果没有执行,那么使用xargs这里还有另一个问题...)
Michael Mol

5

解决这个问题的更好方法(IMO)是:

  • zsh

    l=(a b c)
    mycommand -f$^l

    或使用数组压缩,以便将参数不附加到该选项:

    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的老式shell bash,您可以始终这样做(仍然允许$@数组元素中的任何字符):

set -- a b c
for i do set -- "$@" -f "$i"; shift; done
mycommand "$@"

1
在bash中执行此操作的另一种方法是使用命名数组变量。 for i; do args+=('-f' "$i");done; mycommand "${args[@]}"。如果IDK更快,但将2个元素追加到数组似乎应该是O(n),而set循环可能每次都会复制并重新解析累积的arg列表(O(n ^ 2))。
彼得·科德斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.