如何将命令输出作为多个参数传递给另一个命令

25
我想将一个命令的每个输出作为第二个命令的多个参数传递,例如:
grep "pattern" input

返回:

file1
file2
file3

我想复制这些输出,例如:

cp file1  file1.bac
cp file2  file2.bac
cp file3  file3.bac

我该怎么一次性完成这件事?就像这样:

grep "pattern" input | cp $1  $1.bac

使用命令xargs - el.pescado - нет войне
我猜你的意思是 grep -l... 或者 input 包含文件名列表,你想要在其中的一个子集中进行 grep。 - tripleee
请参见echo命令无法使用管道 - tripleee
请参阅 bash pwd and open with pipe not working,其中有非常详细的解释。 - tripleee
5个回答

34

你可以使用xargs

grep 'pattern' input | xargs -I% cp "%" "%.bac"

11

您可以使用 $() 插入命令的输出结果。因此,您可以使用 kill -9 $(grep -hP '^\d+$' $(ls -lad /dir/*/pid | grep -P '/dir/\d+/pid' | awk '{ print $9 }'))


6

为了完整起见,我还会提到命令替换,并解释为什么不建议使用:

cp $(grep -l "pattern" input) directory/

(反引号语法 cp `grep -l "pattern" input` directory/ 大致相当,但已经过时且笨重; 不要使用它。)

如果grep的输出产生包含空格或shell元字符的文件名,则此方法将失败。

当然,如果您确切知道grep可以产生哪些文件名,并验证了它们中没有问题文件名,那么使用此方法是可以的。但对于生产脚本,请不要使用此方法。

无论如何,在需要单独引用每个匹配项并为其添加扩展名的情况下,xargswhile read替代方案都更优。

在最坏的情况下(指有问题或未指定的文件名),通过xargs将匹配项传递给子shell:

grep -l "pattern" input |
xargs -r sh -c 'for f; do cp "$f" "$f.bac"; done' _

...其中显然for循环内的脚本可以任意复杂。

在理想情况下,你想要运行的命令足够简单(或多功能),以至于你可以简单地传递一个任意长的文件名列表给它。例如,GNU cp 有一个-t选项来方便使用xargs-t选项允许你将目标目录放在命令行的最前面,所以你可以在命令的末尾放置任意多的文件):

grep -l "pattern" input | xargs cp -t destdir

这将扩展为

cp -t destdir file1 file2 file3 file4 ...

对于所有符合xargs可以适应cp命令行的匹配项,重复多次直到将所有文件传递给cp。(不幸的是,这并不符合OP的情况;如果您需要在复制时重命名每个文件,则需要每个cp调用只传递两个参数:源文件名和要将其复制到的目标文件名。)
换句话说,如果您使用命令替换语法,并且grep生成了一个非常长的匹配列表,则可能会遇到ARG_MAX和"Argument list too long"错误;但是xargs将通过仅复制它可以安全传递给cp的参数数量来避免此问题,并在必要时运行多次cp
上述内容仍然无法正确处理包含换行符的文件名。也许还可以参考https://mywiki.wooledge.org/BashFAQ/020

5

除了Chris Jester-Young的很好的回答,我认为xargs也是这些情况的一个好解决方案:

grep ... `ls -lad ... | awk '{ print $9 }'` | xargs kill -9

会让它实现。一起来:

grep -hP '^\d+$' `ls -lad /dir/*/pid | grep -P '/dir/\d+/pid' | awk '{ print $9 }'` | xargs kill -9

1
#!/bin/bash

for f in files; do
  if grep -q PATTERN "$f"; then
    echo cp -v "$f" "${f}.bac"
  fi
done

文件可以是 *.txt 或者 *.text,这基本上意味着以 *.txt 或 *text 结尾的文件,或者用你想要/需要的东西进行替换,当然,如果您对输出满意,请删除 echo。对于递归解决方案,请查看 bash shell 选项 globstar。保留 html 标签。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接