如何测试命令是否输出空字符串?
答案 0 :(得分:240)
以前,问题是如何检查目录中是否有文件。以下代码实现了这一点,但请参阅rsp's answer以获得更好的解决方案。
命令不返回值 - 它们输出它们。您可以使用 command substitution 捕获此输出;例如$(ls -A)
。您可以在Bash中测试非空字符串,如下所示:
if [[ $(ls -A) ]]; then
echo "there are files"
else
echo "no files found"
fi
请注意,我使用了-A
而不是-a
,因为它省略了符号当前(.
)和父(..
)目录条目。
注意:正如评论中所指出的,命令替换不会捕获尾随换行符。因此,如果命令仅输出 换行符,则替换将不会捕获任何内容,并且测试将返回false。尽管不太可能,但在上面的示例中这是可能的,因为单个换行符是有效的文件名!有关详情,请参见this answer。
如果要检查命令是否成功完成,可以检查$?
,其中包含最后一个命令的退出代码(成功为零,失败为非零)。例如:
files=$(ls -A)
if [[ $? != 0 ]]; then
echo "Command failed."
elif [[ $files ]]; then
echo "Files found."
else
echo "No files found."
fi
更多信息here。
答案 1 :(得分:74)
if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]; then ...; fi
感谢 netj
有关改进原文的建议:
if [[ $(ls -A | wc -c) -ne 0 ]]; then ...; fi
这是一个老问题,但我发现至少有两件事需要改进或至少有一些澄清。
我看到的第一个问题是,此处提供的大多数示例根本无法正常工作。它们使用ls -al
和ls -Al
命令 - 两者都在空目录中输出非空字符串。这些示例始终报告有文件,即使没有。
出于这个原因,你应该只使用ls -A
- 为什么有人想要使用-l
开关,这意味着"使用长列表格式"当你想要的只是测试是否有任何输出时,无论如何?
所以这里的大部分答案都是不正确的。
第二个问题是,虽然某些答案工作正常(不使用ls -al
或ls -Al
,但{{ 1}}代替)他们都做这样的事情:
我建议做的是:
ls -A
例如,而不是:
using head -c1
我会用:
if [[ $(ls -A) ]]
而不是:
if [[ $(ls -A | wc -c) -ne 0 ]]
# or:
if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]
我会用:
if [ -z "$(ls -lA)" ]
等等。
对于小输出,它可能不是问题,但对于较大的输出,差异可能很大:
if [ $(ls -lA | wc -c) -eq 0 ]
# or:
if [ $(ls -lA | head -c1 | wc -c) -eq 0 ]
将其与:
进行比较$ time [ -z "$(seq 1 10000000)" ]
real 0m2.703s
user 0m2.485s
sys 0m0.347s
甚至更好:
$ time [ $(seq 1 10000000 | wc -c) -eq 0 ]
real 0m0.128s
user 0m0.081s
sys 0m0.105s
Will Vousden回答的更新示例:
$ time [ $(seq 1 10000000 | head -c1 | wc -c) -eq 0 ]
real 0m0.004s
user 0m0.000s
sys 0m0.007s
在 netj :
的建议后再次更新if [[ $(ls -A | wc -c) -ne 0 ]]; then
echo "there are files"
else
echo "no files found"
fi
如果您正在测试的命令可以输出一些您想要视为空字符串的空格,那么请改为:
if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]; then
echo "there are files"
else
echo "no files found"
fi
你可以使用:
| wc -c
或| tr -d ' \n\r\t ' | wc -c
:
head -c1
或类似的东西。
首先,使用工作。
其次,避免在RAM中不必要的存储和处理潜在的巨大数据。
答案并没有指明输出总是很小,因此也需要考虑大输出的可能性。
答案 2 :(得分:32)
if [ -z "$(ls -lA)" ]; then
echo "no files found"
else
echo "There are files"
fi
这将运行该命令并检查返回的输出(字符串)是否具有零长度。 您可能需要检查'test' manual pages是否有其他标志。
在正在检查的参数周围使用“”,否则空结果将导致语法错误,因为没有给出第二个参数(要检查)!
注意:ls -la
始终返回.
和..
,因此使用它不起作用,请参阅ls manual pages。此外,虽然这看似简单方便,但我认为它很容易破解。根据结果编写一个返回0或1的小脚本/应用程序更加可靠!
答案 3 :(得分:17)
对于那些想要一个优雅的,独立于bash版本的解决方案(实际上应该在其他现代shell中工作)以及那些喜欢使用单行程来快速完成任务的人。开始了!
ls | grep . && echo 'files found' || echo 'files not found'
(请注意,其中一条评论为ls -al
,事实上只有-l
和-a
都会返回一些内容,所以在我的回答中我使用简单的ls
答案 4 :(得分:10)
正如Jon Lin所评论的那样,ls -al
将始终输出(.
和..
)。您希望ls -Al
避免这两个目录。
例如,您可以将命令的输出放入shell变量中:
v=$(ls -Al)
较旧的,不可嵌套的符号
v=`ls -Al`
但我更喜欢可嵌套的符号$(
... )
您可以测试该变量是否为非空
if [ -n "$v" ]; then
echo there are files
else
echo no files
fi
您可以将两者合并为if [ -n "$(ls -Al)" ]; then
答案 5 :(得分:9)
-z string
True if the length of string is zero.
-n string
string
True if the length of string is non-zero.
您可以使用速记版本:
if [[ $(ls -A) ]]; then
echo "there are files"
else
echo "no files found"
fi
答案 6 :(得分:4)
我猜你想要ls -al
命令的输出,所以在bash中,你会有类似的东西:
LS=`ls -la`
if [ -n "$LS" ]; then
echo "there are files"
else
echo "no files found"
fi
答案 7 :(得分:2)
这是针对更极端情况的解决方案:
if [ `command | head -c1 | wc -c` -gt 0 ]; then ...; fi
这将有效
然而,
答案 8 :(得分:0)
到目前为止给出的所有答案都处理命令终止并输出非空字符串。
大多数内容在以下意义上被打破:
yes
)。因此,要解决所有这些问题,并有效地回答以下问题,
如何测试命令是否输出空字符串?
你可以使用:
if read -n1 -d '' < <(command_here); then
echo "Command outputs something"
else
echo "Command doesn't output anything"
fi
您还可以添加一些超时,以便使用read
的{{1}}选项测试命令是否在给定时间内输出非空字符串。例如,超时2.5秒:
-t
备注。如果您认为需要确定命令是否输出非空字符串,则很可能存在XY问题。
答案 9 :(得分:0)
这是另一种方法,它将某些命令的std-out和std-err写入临时文件,然后检查该文件是否为空。这种方法的一个好处是它捕获两个输出,并且不使用子壳或管道。后面的这些方面很重要,因为它们会干扰陷阱bash退出处理(例如here)
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"
答案 10 :(得分:0)
有时你想保存输出,如果它是非空的,则将它传递给另一个命令。如果是这样,你可以使用像
这样的东西list=`grep -l "MY_DESIRED_STRING" *.log `
if [ $? -eq 0 ]
then
/bin/rm $list
fi
这样,如果列表为空,rm
命令就不会挂起。
答案 11 :(得分:0)
与mentioned by tripleee in the question comments一样,使用moreutils ifne
(如果输入不为空)。
在这种情况下,我们希望{em}否定测试的ifne -n
:
ls -A /tmp/empty | ifne -n command-to-run-if-empty-input
当初始命令的输出为非空时,它比其他许多答案的优势。 ifne
将立即开始将其写入STDOUT,而不是先缓冲整个输出,然后再写入,这对于初始输出缓慢生成或过长并且将溢出Shell变量的最大长度非常重要。 / p>
moreutils中有一些utils可以说应该包含在coreutils中,如果您花费大量时间住在shell中,那么值得一试。
OP可能特别感兴趣的dirempty/exists
工具在撰写本文时仍在考虑中,并且已经使用了一段时间(它可能会使用颠簸)。
答案 12 :(得分:0)
有时“某物”可能不是测试应用程序的 stdout 而是 stderr ,因此这是更通用的修复方法:
if [[ $(partprobe ${1} 2>&1 | wc -c) -ne 0 ]]; then
echo "require fixing GPT parititioning"
else
echo "no GPT fix necessary"
fi