我是bash的新手,我正在努力了解xargs
的用法,这对我来说仍然不太清楚。例如:
history | grep ls
我在这里搜索历史记录中的ls
命令。在这个命令中,我没有使用xargs
,它工作正常。
find /etc - name "*.txt" | xargs ls -l
我这个,我必须使用xargs
,但我仍然无法理解差异,我无法正确决定何时使用xargs
,何时不能。
答案 0 :(得分:6)
要回答您的问题,当您需要从一个命令获取输出并将其用作另一个命令的参数时,可以使用xargs
。在第一个示例中,grep
从标准输入中获取数据,而不是作为参数。因此,不需要xargs
。
xargs
从标准输入获取数据并执行命令。默认情况下,数据作为参数附加到命令的末尾。但是,它可以插入任何位置,使用占位符进行输入。传统的占位符是{}
;使用它,您的示例命令可能会写为:
find /etc -name "*.txt" | xargs -I {} ls -l {}
如果/etc
中有3个文本文件,您将获得每个文件的完整目录列表。当然,您可以轻松编写ls -l /etc/*.txt
并省去麻烦。
另一个示例允许您重命名这些文件,并要求占位符{}
使用两次。
find /etc -name "*.txt" | xargs -I {} mv {} {}.bak
这些都是不好的例子,只要你有一个包含空格的文件名就会中断。您可以通过告诉find
将文件名与空字符分开来解决这个问题。
find /etc -print0 -name "*.txt" | xargs -I {} -0 mv {} {}.bak
我个人认为,使用xargs
几乎总有其他选择,学习这些内容会更好。
答案 1 :(得分:3)
简短回答:暂时避免使用xargs
。当您编写了数十个或数百个脚本时,请返回xargs
。
命令可以从参数(例如rm bad_example
)获取输入,也可以从stdin
获取输入(不仅仅是rm -i is_this_bad_too
之后问题的y,还有read answer
})。其他命令(如grep
和sed
)将查找参数,当参数不显示输入时,切换到输入。
你的grep
示例可以很好地从stdin读取,没有什么特别需要
您的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
首先尝试在/ etc中有a nasty filename with spaces.txt
时查看哪个命令最佳。
答案 2 :(得分:0)
xargs(1)是危险的(损坏,可利用等)。
如果您正在处理文件名,请改用find
的-exec [command] {} +。
如果您可以获得NUL分隔的输出,请使用xargs -0
。
答案 3 :(得分:0)
GNU Parallel可以和xargs一样,但没有破坏和可利用的功能#34;。
您可以通过查看示例http://www.gnu.org/software/parallel/man.html#EXAMPLE:-Working-as-xargs--n1.-Argument-appending并阅读教程http://www.gnu.org/software/parallel/parallel_tutorial.html
来学习GNU Parallel答案 4 :(得分:0)
使用不带xargs
的管道时,实际数据将输入到下一个命令中。另一方面,当使用带有xargs
的管道时,实际数据将作为下一条命令的参数查看。举一个具体的例子,假设您有一个包含a.txt
和b.txt
的文件夹。 a.txt
仅包含一行' hello world!',而b.txt
仅是空白。
如果愿意
ls | grep txt
您最终将获得输出。
a.txt
b.txt
但是,如果您这样做
ls | xargs grep txt
您将一无所获,因为文件a.txt和b.txt都不包含单词 txt 。如果命令是
ls | xargs grep hello
您会得到
hello world!
这是因为在xargs
中,ls
给出的两个文件名被作为参数而不是实际内容传递给grep
。