Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 在进行管道时何时使用xargs?_Bash_Xargs - Fatal编程技术网

Bash 在进行管道时何时使用xargs?

Bash 在进行管道时何时使用xargs?,bash,xargs,Bash,Xargs,我是bash新手,我正在尝试理解xargs的用法,这对我来说还不清楚。例如: history | grep ls 我在这里搜索历史记录中的命令ls。在这个命令中,我没有使用xargs,它工作得很好 find /etc - name "*.txt" | xargs ls -l 在这一次,我不得不使用xargs,但我仍然无法理解其中的区别,我无法正确决定何时使用xargs,何时不使用。xargs(1)在读取非NUL分隔的输入时是危险的(损坏、可利用等) 如果您使用的是文件名,请改用find的-e

我是bash新手,我正在尝试理解
xargs
的用法,这对我来说还不清楚。例如:

history | grep ls
我在这里搜索历史记录中的命令
ls
。在这个命令中,我没有使用
xargs
,它工作得很好

find /etc - name "*.txt" | xargs ls -l
在这一次,我不得不使用
xargs
,但我仍然无法理解其中的区别,我无法正确决定何时使用
xargs
,何时不使用。

xargs(1)在读取非NUL分隔的输入时是危险的(损坏、可利用等)

如果您使用的是文件名,请改用
find
的-exec[command]{}+命令。
如果您可以获得NUL分隔的输出,请使用
xargs-0

简短回答:暂时避免
xargs
。编写了几十个或数百个脚本后,返回到
xargs

命令可以从参数(如
rm bad\u示例
)获取输入,也可以从
stdin
获取输入(不仅仅是
rm-i后面问题的y也是这个\u bad\u
,还可以从
读取答案
)。其他命令,如
grep
sed
将查找参数,当参数不显示输入时,切换到输入。
您的
grep
示例可以从stdin中很好地阅读,没有什么特别需要的。
您的
ls
需要find的输出作为参数
xargs
只是扭转局面的一种方法。有关xargs的更多信息,请使用
man xargs
。备选方案:

find /etc -name "*.txt" -exec ls -l {} \;
find /etc -name "*.txt" -ls
ls -l $(find /etc -name "*.txt" )
ls /etc/*.txt

首先,当您在/etc中有一个带有空格.txt的讨厌文件名时,请尝试看看这两个命令中的哪一个是最好的。

GNU Parallel可以做与xargs相同的事情,但没有损坏的和可利用的“功能”


通过查看示例和浏览教程,您可以学习GNU并行。要回答您的问题,当您需要从一个命令获取输出并将其用作另一个命令的参数时,可以使用
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
,几乎总是有其他替代方法,学习这些方法会更好地为您服务。

当您使用不带
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
,而不是实际内容。

@SaraHamad:通过将
-print0
添加到cmd行,您可以从查找中获得以null结尾的字符串。检查你的手册页。(大多数新版本都有)如果要确保读取空分隔的输入,最好使用IFS=read-r-d''行来读取,不是更好吗?@DirkHerrmann您是对的。虽然我是为一般情况写的。根据你的评论,我删除了这个部分。作为“危险的(坏的,可利用的,等等)”,并不意味着它对于一次性脚本研磨几十个文件不是超级有用:)@JakubM。滚到尘土里去!底线是命令行的大小有一个限制。(这是一个硬编码数字,通常
128KiB
)请参阅。当您的命令行超过该大小时,您可以选择使用
xargs
,它将打破该大小并为您处理该命令。如果您觉得它有用,我将使用以下方法: