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

问题描述 投票:0回答:5

我想将命令的每个输出作为多个参数传递给第二个命令,例如:

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
linux shell unix
5个回答
35
投票

您可以使用

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
可以生成哪些文件名,并且已经验证它们都没有问题,那么使用它就可以了。但对于生产脚本,不要使用这个。

无论如何,对于OP的场景,您需要单独引用每场比赛并为其添加扩展,

xargs
while 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
选项允许您将目标目录 first 放在命令行上,因此您可以放置尽可能多的文件)你喜欢在命令末尾):

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


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 结尾的文件,或者替换为您想要/需要的内容,当然将 PATTERN 替换为您的。如果您对输出满意,请删除 echo。对于递归解决方案,请查看 bash shell 选项 globstar

© www.soinside.com 2019 - 2024. All rights reserved.