我想将命令的每个输出作为多个参数传递给第二个命令,例如:
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
cho*_*oba 18
你可以使用xargs:
grep 'pattern' input | xargs -I% cp "%" "%.bac"
您可以使用$()插值命令的输出.所以,kill -9 $(grep -hP '^\d+$' $(ls -lad /dir/*/pid | grep -P '/dir/\d+/pid' | awk '{ print $9 }'))如果你愿意,你可以使用.
为了完整起见,我还将提到命令替换并解释为什么不建议这样做:
cp $(grep -l "pattern" input) directory/
(反引号语法 cp `grep -l "pattern" input` directory/大致相同,但它已经过时且难以使用;不要使用它。)
grep如果输出生成的文件名包含空格或 shell 元字符,则此操作将会失败。
当然,如果您确切地知道可以grep生成哪些文件名,并且已经验证它们都没有问题,那么使用它就可以了。但对于生产脚本,不要使用它。
无论如何,对于 OP 的场景,您需要单独引用每个匹配项并为其添加扩展,无论如何xargs, 或while read替代方案都更好。
在最坏的情况下(意味着有问题或未指定的文件名),通过以下方式将匹配项传递到子 shell xargs:
grep -l "pattern" input |
xargs -r sh -c 'for f; do cp "$f" "$f.bac"; done' _
...显然循环内的脚本for可以任意复杂。
在理想情况下,您要运行的命令足够简单(或通用),您可以简单地向其传递任意长的文件名列表。例如,GNUcp有一个-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“参数列表太长”错误;但xargs将通过一次仅复制可以安全传递的尽可能多的参数来专门避免这种情况cp,并cp在必要时运行多次。
如果您的文件名包含换行符,上述方法仍然无法正常工作。也许另请参阅https://mywiki.wooledge.org/BashFAQ/020
除了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
| 归档时间: | 
 | 
| 查看次数: | 5237 次 | 
| 最近记录: |