bash 管道时何时使用 xargs?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35589179/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When to use xargs when piping?
提问by Sara Hamad
I am new to bash and I am trying to understand the use of xargs
, which is still not clear for me. For example:
我是 bash 的新手,我试图了解 的使用xargs
,这对我来说仍然不清楚。例如:
history | grep ls
Here I am searching for the command ls
in my history. In this command, I did not use xargs
and it worked fine.
在这里,我正在ls
我的历史记录中搜索命令。在这个命令中,我没有使用xargs
,它运行良好。
find /etc - name "*.txt" | xargs ls -l
I this one, I had to use xargs
but I still can not understand the difference and I am not able to decide correctly when to use xargs
and when not.
我这个,我不得不使用,xargs
但我仍然无法理解其中的区别,我无法正确决定何时使用xargs
,何时不使用。
采纳答案by miken32
To answer your question, xargs
can be used when you need to take the output from one command and use it as an argument to another. In your first example, grep
takes the data from standard input, rather than as an argument. So, xargs
is not needed.
要回答您的问题,xargs
可以在您需要从一个命令中获取输出并将其用作另一个命令的参数时使用。在您的第一个示例中,grep
从标准输入中获取数据,而不是作为参数。所以,xargs
是不需要的。
xargs
takes data from standard input and executes a command. By default, the data is appended to the end of the command as an argument. It can be inserted anywhere however, using a placeholder for the input. The traditional placeholder is {}
; using that, your example command might then be written as:
xargs
从标准输入获取数据并执行命令。默认情况下,数据作为参数附加到命令的末尾。然而,它可以插入到任何地方,使用占位符作为输入。传统的占位符是{}
; 使用它,您的示例命令可能会写为:
find /etc -name "*.txt" | xargs -I {} ls -l {}
If you have 3 text files in /etc
you'll get a full directory listing of each. Of course, you could just have easily written ls -l /etc/*.txt
and saved the trouble.
如果您有 3 个文本文件,/etc
您将获得每个文件的完整目录列表。当然,您可以轻松编写ls -l /etc/*.txt
并省去麻烦。
Another example lets you rename those files, and requires the placeholder {}
to be used twice.
另一个示例让您重命名这些文件,并要求{}
使用两次占位符。
find /etc -name "*.txt" | xargs -I {} mv {} {}.bak
These are both bad examples, and will break as soon as you have a filename containing whitespace. You can work around that by telling find
to separate filenames with a null character.
这些都是不好的例子,一旦你的文件名包含空格就会中断。您可以通过告诉find
用空字符分隔文件名来解决这个问题。
find /etc -print0 -name "*.txt" | xargs -I {} -0 mv {} {}.bak
My personal opinion is that there are almost always alternatives to using xargs
, and you will be better served by learning those.
我个人的观点是,几乎总是有使用 的替代方法xargs
,学习这些方法会更好地为您服务。
回答by Walter A
Short answer: Avoid xargs
for now. Return to xargs
when you have written dozens or hundreds of scripts.
简短回答:暂时避免xargs
。xargs
当您编写了数十个或数百个脚本时返回。
Commands can get their input from parameters (like rm bad_example
) or can get the input from stdin
(not just the y on the question after rm -i is_this_bad_too
, but also read answer
). Other commands like grep
and sed
will look for parameters and when the parameters don't show the input, switch to the input.
Your grep
example works fine reading from stdin, nothing special needed.
Your ls
needs the output of find as a parameter. xargs
is just one way to turn things around. Use man xargs
for more about xargs. Alternatives:
命令可以从参数(如rm bad_example
)获取输入,也可以从stdin
(不仅是 之后问题上的 y rm -i is_this_bad_too
,还有read answer
)获取输入。其他命令如grep
和sed
将查找参数,当参数不显示输入时,切换到输入。
您的grep
示例可以从标准输入正常读取,没有什么特别需要的。
您ls
需要将 find 的输出作为参数。xargs
只是扭转局面的一种方式。用于man xargs
了解更多关于 xargs 的信息。备择方案:
find /etc -name "*.txt" -exec ls -l {} \;
find /etc -name "*.txt" -ls
ls -l $(find /etc -name "*.txt" )
ls /etc/*.txt
First try to see which of this commands is best when you have a nasty filename with spaces.txt
in /etc.
首先尝试查看a nasty filename with spaces.txt
在 /etc 中有哪些命令是最好的。
回答by Nothing More
When you use piping without xargs
, the actual data is fed into the next command. On the other hand, when using piping with xargs
, the actual data is viewed as a parameter to the next command. To give a concrete example, say you have a folder with a.txt
and b.txt
. a.txt
contains just a single line 'hello world!', and b.txt
is just empty.
当您使用不带xargs
的管道时,实际数据将输入下一个命令。另一方面,当使用带有xargs
的管道时,实际数据被视为下一个命令的参数。举一个具体的例子,假设你有一个文件夹a.txt
和b.txt
。a.txt
只包含一行' hello world! ',并且b.txt
只是空的。
If you do
如果你这样做
ls | grep txt
you would end up getting the output:
你最终会得到输出:
a.txt
b.txt
Yet, if you do
然而,如果你这样做
ls | xargs grep txt
you would get nothing since neither file a.txt nor b.txt contains the word txt.
你什么也得不到,因为文件 a.txt 和 b.txt 都不包含单词txt。
If the command is
如果命令是
ls | xargs grep hello
you would get:
你会得到:
hello world!
That's because with xargs
, the two filenames given by ls
are passed to grep
as arguments, rather than the actual content.
那是因为 with xargs
,由 给出的两个文件名作为参数ls
传递给grep
,而不是实际内容。
回答by Ole Tange
GNU Parallel can do the same as xargs, but does not have the broken and exploitable "features".
GNU Parallel 可以执行与 xargs 相同的操作,但没有损坏和可利用的“功能”。
You can learn GNU Parallel by looking at examples http://www.gnu.org/software/parallel/man.html#EXAMPLE:-Working-as-xargs--n1.-Argument-appendingand walking through the tutorial http://www.gnu.org/software/parallel/parallel_tutorial.html
您可以通过查看示例http://www.gnu.org/software/parallel/man.html#EXAMPLE:-Working-as-xargs--n1.-Argument-appending并浏览教程http: //www.gnu.org/software/parallel/parallel_tutorial.html
回答by Rany Albeg Wein
xargs(1) is dangerous (broken, exploitable, etc.) when reading non-NUL-delimited input.
xargs(1) 在读取非 NUL 分隔的 input时很危险(损坏、可利用等)。
If you're working with filenames, use find
's -exec [command] {} + instead.
If you can get NUL-delimited output, use xargs -0
.
如果您正在处理文件名,请改用find
's -exec [command] {} +。如果您可以获得以 NUL 分隔的输出,请使用xargs -0
.