我该如何测试一个命令是否输出空字符串?
先前的问题是如何检查目录中是否有文件。下面的代码可以实现这一点,但请查看rsp的答案,以获得更好的解决方案。
命令不会返回值——它们会输出它们。您可以使用命令替换来捕获这个输出;例如$(ls -A)
。你可以像这样在Bash中测试非空字符串:
if [[ $(ls -A) ]]; then
echo "there are files"
else
echo "no files found"
fi
请注意,我使用的是-A
而不是-a
,因为它省略了符号当前目录(.
)和父级目录(..
)的条目。
注意:正如评论中指出的那样,命令替换不会捕获尾随换行符。 因此,如果命令只输出换行符,则替换将捕获到空值,测试将返回false。 虽然这在上面的示例中非常不可能发生,因为单个换行符是有效的文件名! 更多信息请参见此答案。
如果您想检查命令是否成功完成,可以检查$?
,其中包含最后一个命令的退出代码(成功为零,失败为非零)。 例如:
files=$(ls -A)
if [[ $? != 0 ]]; then
echo "Command failed."
elif [[ $files ]]; then
echo "Files found."
else
echo "No files found."
fi
更多信息在这里。
-n
,这样就只需写成 if [[ $(ls -A) ]]; then
。 - user$(ls -A)
的文件,重新运行ls -A
是否明智?或者在第一次调用时,我们可以保存其输出并打印它。 - alperif [[ $(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
,而是使用ls -A
),但它们都做了类似这样的事情:
我建议改为:
head -c1
计算最多1个字符的数量因此,例如,代替:
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
$ time [ $(seq 1 10000000 | head -c1 | wc -c) -eq 0 ]
real 0m0.004s
user 0m0.000s
sys 0m0.007s
这是基于Will Vousden的答案更新后的示例:
if [[ $(ls -A | wc -c) -ne 0 ]]; then
echo "there are files"
else
echo "no files found"
fi
在netj的建议下再次更新:
if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]; then
echo "there are files"
else
echo "no files found"
fi
jakeonfire 的额外更新:grep
将以失败退出。我们可以利用这一点稍微简化语法:if ls -A | head -c1 | grep -E '.'; then
echo "there are files"
fi
if ! ls -A | head -c1 | grep -E '.'; then
echo "no files found"
fi
如果你正在测试的命令可能会输出一些你想要将其视为空字符串的空格,那么可以使用以下方法代替:
| wc -c
您可以使用以下方法:
| tr -d ' \n\r\t ' | wc -c
head -c1
命令:| tr -d ' \n\r\t ' | head -c1 | wc -c
首先,使用一个可行的命令。
其次,避免在RAM中存储不必要的数据和处理可能非常庞大的数据。
答案没有指定输出总是很小,因此还需要考虑大量输出的可能性。
[[ $(... | head -c | wc -c) -gt 0 ]]
或者 [[ -n $(... | head -c1) ]]
更好,因为 wc -c
需要消耗命令的全部输出。 - netjif [ -z "$(ls -lA)" ]; then
echo "no files found"
else
echo "There are files"
fi
$(
而不是反引号,因为 $(
嵌套更好。 - Basile Starynkevitch对于那些想要一个优雅的、独立于Bash版本的解决方案(实际上应该在其他现代shell中也适用),以及喜欢使用一行代码快速完成任务的人。我们来看看吧!
ls | grep . && echo 'files found' || echo 'files not found'
(正如其中一条评论所提到的,ls -al
和实际上只有 -l
和 -a
都会返回内容,因此在我的回答中我使用简单的 ls
)
grep -q ^
,换行符也将被匹配,grep 将不会向标准输出打印任何内容。此外,它会在收到任何输入后立即退出,而不是等待其输入流结束。 - mortehu-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
string
只是 -n string
的同义词。 - user正如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
有时候,ls
可能是一些shell 别名。你可能更喜欢使用$(/bin/ls -Al)
。请参阅ls(1)和hier(7)以及environ(7)和你的~/.bashrc
(如果你的shell是GNU bash;我使用的互动式shell是zsh,在/etc/passwd
中定义-请参阅passwd(5)和chsh(1))。
我猜您想要ls -al
命令的输出,所以在bash中,您可以使用以下命令:
LS=`ls -la`
if [ -n "$LS" ]; then
echo "there are files"
else
echo "no files found"
fi
if [[ $(partprobe ${1} 2>&1 | wc -c) -ne 0 ]]; then
echo "require fixing GPT parititioning"
else
echo "no GPT fix necessary"
fi
if [ `command | head -c1 | wc -c` -gt 0 ]; then ...; fi
这将适用于所有 Bourne shell;
然而,
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"
ifne
。https://joeyh.name/code/moreutils/ - tripleee