管道何时使用xargs?

Sar*_*mad 8 bash xargs

我是bash的新手,我正在努力了解使用xargs,这对我来说仍然不明确.例如:

history | grep ls
Run Code Online (Sandbox Code Playgroud)

我在这里寻找ls历史上的命令.在这个命令中,我没有使用xargs它,它工作正常.

find /etc - name "*.txt" | xargs ls -l
Run Code Online (Sandbox Code Playgroud)

我这个,我必须使用,xargs但我仍然无法理解差异,我无法正确决定何时使用xargs,何时不能.

Not*_*ore 9

当您使用不带xargs的管道时,实际数据将输入下一个命令。另一方面,当使用带有xargs的管道时,实际数据被视为下一个命令的参数。举一个具体的例子,假设你有一个文件夹a.txtb.txta.txt只包含一行' hello world! ',并且b.txt只是空的。

如果你这样做

ls | grep txt
Run Code Online (Sandbox Code Playgroud)

你最终会得到输出:

a.txt
b.txt
Run Code Online (Sandbox Code Playgroud)

然而,如果你这样做

ls | xargs grep txt
Run Code Online (Sandbox Code Playgroud)

你什么也得不到,因为文件 a.txt 和 b.txt 都不包含单词txt

如果命令是

ls | xargs grep hello
Run Code Online (Sandbox Code Playgroud)

你会得到:

hello world!
Run Code Online (Sandbox Code Playgroud)

那是因为 with xargs,由 给出的两个文件名作为参数ls传递给grep,而不是实际内容。


mik*_*n32 7

要回答您的问题,xargs可以在需要从一个命令获取输出并将其用作另一个命令的参数时使用.在第一个示例中,grep从标准输入中获取数据,而不是作为参数.所以,xargs不需要.

xargs从标准输入获取数据并执行命令.默认情况下,数据作为参数附加到命令的末尾.但是,它可以插入任何位置,使用占位符进行输入.传统的占位符是{}; 使用它,您的示例命令可能会写为:

find /etc -name "*.txt" | xargs -I {} ls -l {}
Run Code Online (Sandbox Code Playgroud)

如果您有3个文本文件,/etc您将获得每个文件的完整目录列表.当然,你可以轻松编写ls -l /etc/*.txt并省去麻烦.

另一个示例允许您重命名这些文件,并要求占位符{}使用两次.

find /etc -name "*.txt" | xargs -I {} mv {} {}.bak
Run Code Online (Sandbox Code Playgroud)

这些都是不好的例子,只要你有一个包含空格的文件名就会中断.您可以通过告诉find使用空字符分隔文件名来解决这个问题.

find /etc -print0 -name "*.txt" | xargs -I {} -0 mv {} {}.bak
Run Code Online (Sandbox Code Playgroud)

我的个人意见是,几乎总有其他的替代方案可供使用xargs,通过学习这些方法,您将获得更好的服务.


Ger*_*ira 5

了解数据流

当管道运算符将stdout从最后一个命令|重定向到下一个命令的stdin时,该命令会从stdin构建并执行命令。xargs

简而言之:

  • | 标准输出 ->标准输入
  • xargs标准输入 ->命令参数

由于 xargs 碰巧期望管道运算符的结果,因此两者的组合可以方便地将 stdout 转换为命令参数:

  • | xargsstdout -> stdin (管道) ->命令参数(xargs)

何时使用|| xargs

简而言之,这取决于您想要执行的命令,因为不同的命令以不同的方式处理标准输入命令参数,具体取决于它的实现。

换句话说,即使同时接受 stdin 和参数的命令也会根据您提供的其中之一而表现不同,如下面的示例所示。

不过,如果您想要某种规则,您可以认为:

  • 如果您希望命令处理的数据已在 stdout 中则应使用管道运算符|
  • 如果 stdout 包含要处理其内容的文件名,甚至包含用于更改命令默认行为的参数,则应使用组合| xargs;

但是,请做好例外情况的准备。


例子

为下一个示例设置场景:

echo "hello_world_content" > "hello_world.txt"
# Creates a file named "hello_world.txt" and
# writes "hello_world_content" inside it

Run Code Online (Sandbox Code Playgroud)

命令grep

ls | grep "hello"
# Grep searches for 'hello' in the stdout of the ls command
# Outputs: hello_world.txt


ls | xargs grep "hello"
# Corresponds to: grep 'hello_world.txt'
# Outputs: hello_world_content
Run Code Online (Sandbox Code Playgroud)

命令echo

ls | echo
# Outputs a blank line, as echo seems to ignore the stdin
# Outputs:


ls | xargs echo
# Corresponds to: echo 'hello_world.txt'
# Outputs: hello_world.txt
Run Code Online (Sandbox Code Playgroud)

命令cat

ls | cat
# Reads and prints the stdout of ls
# Outputs: hello_world.txt


ls | xargs cat
# Corresponds to: cat 'hello_world.txt'
# Outputs: hello_world_content
Run Code Online (Sandbox Code Playgroud)

命令cat[第二部分]:

echo "this_file_does_not_exists.txt" | cat
# Reads and prints the stdout of echo
# Outputs: this_file_does_not_exists.txt


echo "this_file_does_not_exists.txt" | xargs cat
# Corresponds to: cat 'this_file_does_not_exists.txt'
# Outputs error: cat: this_file_does_not_exists.txt: No such file or directory
Run Code Online (Sandbox Code Playgroud)