我怎么能测试一个命令输出空字符串?
Answer 1:
此前,这个问题问到如何检查是否有目录中的文件。 下面的代码实现了,但看到RSP的回答了一个更好的解决方案。
空输出
命令不返回值的-他们输出他们。 您可以通过使用捕获该输出命令替换 ; 如$(ls -A)
您可以测试在猛砸非空字符串是这样的:
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
更多信息这里 。
Answer 2:
TL; DR
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
但ls -A
代替)他们都做这样的事情:
- 运行命令
- 缓冲RAM中的整个输出
- 输出转换成一个巨大的单行线
- 该字符串比较空字符串
我建议做,而不是将是:
- 运行命令
- 算上其输出的字符,而不将它们存储
- 甚至更好-数最大为字符的数目
using head -c1
(感谢netj张贴这一想法在下面的评论)
- 甚至更好-数最大为字符的数目
- 对比这一数字为零
因此,例如,而不是:
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
完整的示例
更新由威尔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
丢弃空白
如果您正在测试可以输出一些空白要当作一个空字符串,然后而不是命令:
| wc -c
你可以使用:
| tr -d ' \n\r\t ' | wc -c
或者用head -c1
:
| tr -d ' \n\r\t ' | head -c1 | wc -c
或类似的东西。
摘要
首先,使用效果的命令。
第二,避免了潜在的巨大数据的RAM和处理不必要的存储。
答案没有指定的输出始终是小,所以需要考虑,以及大输出的可能性。
Answer 3:
if [ -z "$(ls -lA)" ]; then
echo "no files found"
else
echo "There are files"
fi
这将运行该命令并检查返回的输出(字符串)是否具有零长度。 你可能要检查的“测试”手册页的其他标志。
使用正在检查“”周围的说法,否则空的结果将导致一个语法错误,因为没有给出第二个参数(检查)!
注意: ls -la
总是返回.
和..
所以使用这是行不通的,看LS手册页 。 此外,虽然这看起来方便和容易的,我想这将打破容易。 写一个小脚本/应用程序,根据结果返回0或1可靠得多!
Answer 4:
对于那些谁想要一个优雅,bash的版本无关的解决方案(其实应该在其他现代shell工作)和那些谁爱用单行快速任务。 开始了!
ls | grep . && echo 'files found' || echo 'files not found'
(注意:作为一个评论提到, ls -al
而事实上,只是-l
和-a
将所有返回的东西,所以我的答案我用简单的ls
Answer 5:
由于乔恩林评论说, 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
if [ -n "$(ls -Al)" ]; then
Answer 6:
巴什参考手册
6.4 Bash的条件表达式
-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
Answer 7:
我猜你想要的输出ls -al
命令,这样在bash,你会碰到这样的:
LS=`ls -la`
if [ -n "$LS" ]; then
echo "there are files"
else
echo "no files found"
fi
Answer 8:
这里有一个更极端的情况下的解决方案:
if [ `command | head -c1 | wc -c` -gt 0 ]; then ...; fi
这将工作
- 所有的Bourne shell;
- 如果命令输出为全零;
- 有效地无论输出大小的;
然而,
- 一旦什么是输出的命令或它的子进程就会被杀死。
Answer 9:
所有的答案给出到目前为止处理终止 ,并输出一个非空字符串命令。
大多数被破坏下面的意义:
- 他们不使用命令只输出换行符妥善处理;
- 从Bash≥4.4最开始将垃圾邮件标准错误,如果命令输出空字节(因为它们使用命令取代);
- 大多数人会发出声音完整输出流,所以会等到命令应答之前终止。 一些命令从未终止(尝试,例如,
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问题。
Answer 10:
下面是写STD-出来的一些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"
Answer 11:
有时你要保存的输出,如果它非空,将它传递给另一个命令。 如果是这样,你可以使用类似
list=`grep -l "MY_DESIRED_STRING" *.log `
if [ $? -eq 0 ]
then
/bin/rm $list
fi
这样, rm
,如果该列表是空的命令不会挂起。