如何测试命令是否输出空字符串?


当前回答

有时“something”可能不是stdout,而是测试应用程序的stderr,所以这里有一个更通用的修复方法:

if [[ $(partprobe ${1} 2>&1 | wc -c) -ne 0 ]]; then
    echo "require fixing GPT parititioning"
else
    echo "no GPT fix necessary"
fi

其他回答

有时您希望保存输出(如果它是非空的),以便将其传递给另一个命令。如果是的话,你可以使用

list=`grep -l "MY_DESIRED_STRING" *.log `
if [ $? -eq 0 ]
then
    /bin/rm $list
fi

这样,如果列表为空,rm命令就不会挂起。

正如tripleee在问题评论中提到的,使用moreutils ifne(如果输入不为空)。

在这种情况下,我们想要ifne -n,它否定测试:

ls -A /tmp/empty | ifne -n command-to-run-if-empty-input

当初始命令的输出为非空时,此方法相对于许多其他答案的优点。ifne将立即开始将其写入STDOUT,而不是缓冲整个输出,然后再写入,如果初始输出生成缓慢或非常长,并且会溢出shell变量的最大长度,这是很重要的。

moreutils中有一些utils可以说应该放在coreutils中——如果你花大量时间生活在shell中,它们值得一试。

对OP特别感兴趣的可能是diempty /exists工具,在撰写本文时仍在考虑中,并且已经有一段时间了(它可能会使用bump)。

到目前为止给出的所有答案都处理终止并输出非空字符串的命令。

大多数是在以下意义上被打破的:

它们不能正确地处理只输出换行符的命令; 从Bash≥4.4开始,如果命令输出null字节(因为他们使用命令替换),大多数将发送垃圾邮件标准错误; 大多数人将发出完整的输出流,所以会等到命令结束才回答。有些命令永远不会终止(例如,尝试,yes)。

所以为了解决所有这些问题,并有效地回答下面的问题,

如何测试命令是否输出空字符串?

你可以使用:

if read -n1 -d '' < <(command_here); then
    echo "Command outputs something"
else
    echo "Command doesn't output anything"
fi

您还可以使用read的-t选项添加一些超时,以测试命令是否在给定时间内输出非空字符串。例如,对于2.5秒的超时:

if read -t2.5 -n1 -d '' < <(command_here); then
    echo "Command outputs something"
else
    echo "Command doesn't output anything"
fi

的话。如果您认为需要确定命令是否输出非空字符串,那么您很可能遇到了XY问题。

下面是另一种方法,将某些命令的std-out和std-err写入临时文件,然后检查该文件是否为空。这种方法的一个好处是它捕获两个输出,并且不使用子外壳或管道。后面这些方面很重要,因为它们会干扰捕获bash退出处理(例如这里)

tmpfile=$(mktemp)
some-command  &> "$tmpfile"
if [[ $? != 0 ]]; then
    echo "Command failed"
elif [[ -s "$tmpfile" ]]; then
    echo "Command generated output"
else
    echo "Command has no output"
fi
rm -f "$tmpfile"

正如Jon Lin所评论的,ls -al将始终输出(for。和. .)。您希望ls -Al避免这两个目录。

例如,你可以把命令的输出放到一个shell变量中:

v=$(ls -Al)

较旧的、非嵌套的符号是

v=`ls -Al`

但我更喜欢嵌套符号$(…)

您可以测试该变量是否为非空

if [ -n "$v" ]; then
    echo there are files
else
    echo no files
fi

你可以把两者结合起来,就像[-n "$(ls -Al)"];然后

有时,ls可能是某个shell别名。您可能更喜欢使用$(/bin/ls -Al)。参见ls(1)和hier(7)和environ(7)和你的~/。bashrc(如果你的shell是GNU bash;我的交互式shell是zsh,定义在/etc/passwd -见passwd(5)和chsh(1))。