如果 stdin 输入为空,如何忽略 xargs 命令?
考虑这个命令:
ls /mydir/*.txt | xargs chown root
目的是将 mydir
中所有文本文件的所有者更改为 root
问题是,如果 mydir
中没有 .txt
文件code> 然后 xargs 抛出错误,指出没有指定路径。这是一个无害的示例,因为会引发错误,但在某些情况下,例如我需要在此处使用的脚本中,假定空白路径是当前目录。因此,如果我从 /home/tom/
运行该命令,那么如果 ls /mydir/*.txt
和 /home/ 下的所有文件没有结果tom/
将其所有者更改为 root。
那么如何让 xargs 忽略空结果呢?
Consider this command:
ls /mydir/*.txt | xargs chown root
The intention is to change owners of all text files in mydir
to root
The issue is that if there are no .txt
files in mydir
then xargs thows an error saying there is no path specified. This is a harmless example because an error is being thrown, but in some cases, like in the script that i need to use here, a blank path is assumed to be the current directory. So if I run that command from /home/tom/
then if there is no result for ls /mydir/*.txt
and all files under /home/tom/
have their owners changed to root.
So how can I have xargs ignore an empty result?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
对于 GNU
xargs
,您可以使用-r
或--no-run-if-empty
选项:在 macOS 上使用的 BSD 版本的
xargs
不会针对空输入运行该命令,因此不需要-r
选项(也不被那个版本的 xargs)。For GNU
xargs
, you can use the-r
or--no-run-if-empty
option:The BSD version of
xargs
, which is used on macOS, does not run the command for an empty input, so the-r
option is not needed (nor is it accepted by that version ofxargs
).非 GNU xargs 的用户可以利用
-L <#lines>
、-n <#args>
、-i
、和-I
:请记住,xargs 在空白处分割行,但可以使用引号和转义; RTFM 了解详情。
此外,正如 Doron Behar 提到的,此解决方法不可移植,因此可能需要检查:
Users of non-GNU xargs may take advantage of
-L <#lines>
,-n <#args>
,-i
, and-I <string>
:Keep in mind that xargs splits the line at whitespace but quoting and escaping are available; RTFM for details.
Also, as Doron Behar mentions, this workaround isn't portable so checks may be needed:
man xargs
说--no-run-if-empty
。man xargs
says--no-run-if-empty
.就
xargs
而言,您可以按照建议使用-r
,但BSDxargs
不支持它。因此,作为解决方法,您可以传递一些额外的临时文件,例如:
或将其 stderr 重定向为 null (
2> /dev/null
),例如另一种更好的方法是使用
迭代找到的文件while
循环:另请参阅:忽略 Mac OS X 中 xargs 的空结果
另请注意,您的方法改变权限不是很好,不鼓励这样做。当然,您不应该解析
ls
命令 的输出(请参阅:为什么你不应该解析 ls 的输出)。特别是当您以 root 身份运行命令时,因为您的文件可能包含可由 shell 解释的特殊字符,或者想象文件在/
周围有空格字符,那么结果可能会很糟糕。因此你应该改变你的方法并使用
find
命令,例如In terms of
xargs
, you can use-r
as suggested, however it's not supported by BSDxargs
.So as workaround you may pass some extra temporary file, for example:
or redirect its stderr into null (
2> /dev/null
), e.g.Another better approach is to iterate over found files using
while
loop:See also: Ignore empty results for xargs in Mac OS X
Also please note that your method of changing the permissions isn't great and it's discouraged. Definitely you shouldn't parse output of
ls
command (see: Why you shouldn't parse the output of ls). Especially when you're running your command by root, because your files can consist special characters which may be interpreted by the shell or imagine the file having a space character around/
, then the results can be terrible.Therefore you should change your approach and use
find
command instead, e.g.使用
-r
/--no-run-if-empty
xargs 参数的跨平台(Mac 和 Linux)替代方案:使用空参数的示例(与Ubuntu 18.04 和 Big Sur):
多行示例:
A cross-platform (Mac and Linux) alternative to using
-r
/--no-run-if-empty
xargs' parameter:Example with empty parameters (same result on Ubuntu 18.04 and Big Sur):
Example with multiple lines:
这是 GNU xargs 的行为,可以使用 -r, --no-run-if-empty 来抑制。
xargs 的 *BSD 变体默认具有此行为,因此不需要 -r。自 FreeBSD 7.1(2009 年 1 月发布)以来,出于兼容性原因,接受 -r 参数(witch 不执行任何操作)。
我个人更喜欢在脚本中使用 longopts,但由于 *BSD xargs 不使用 longopts,只需使用“-r”,并且 xargs 在 *BSD 和
MacOS 上的 Linux 系统(当前为 MacOS Mojave)上的 xargs 的行为相同,遗憾的是不支持“-r”参数。
This is a behaviour of GNU xargs which can be supressed by using -r, --no-run-if-empty.
The *BSD variant of xargs has this behavoir on default, so -r is not needed. Since FreeBSD 7.1 (released in january 2009) an -r argument is accepted (witch does nothing) for compatiblity reasons.
I personally prefer using longopts in scripts but since the *BSD xargs does not uses longopts just use "-r" and xargs will act the same on *BSD an on linux systems
xargs on MacOS (currently MacOS Mojave) sadly don't supports the "-r" argument.
在 OSX 上:Bash 重新实现
xargs
处理-r
参数,将其放入$HOME/bin
并将其添加到>路径:
On OSX: Bash reimplementation of
xargs
dealing with the-r
argument, put that e.g. in$HOME/bin
and add it to thePATH
: