当前目录无JPG文件时,带/不带引号的bash脚本为何结果不同?
问题解析:双引号对命令替换结果的影响
这个差异的核心原因其实很直白:macOS 上的wc -l命令在统计0行时,输出是带前导空格的 0,而双引号的存在与否,直接决定了Shell如何处理这个输出结果。
拆解两个脚本的关键区别
先聚焦两个脚本的核心判断逻辑:
jpg1.sh:[ "$(ls *.jpg | wc -l)" = 0 ]→ 命令替换的结果被双引号完整包裹jpg2.sh:[ $(ls *.jpg | wc -l) = 0 ]→ 命令替换的结果没有双引号包裹
具体执行过程分析
当目录里没有.jpg文件时:
ls *.jpg会抛出错误ls: *.jpg: No such file or directory,但管道后的wc -l依然会统计输入行数——这里没有有效输出,所以wc -l返回0(注意前面有两个空格)。- 带双引号的情况(jpg1.sh):双引号会保留命令替换结果的完整字符串,包括前导空格,所以判断条件变成
[ " 0" = 0 ]。字符串" 0"和纯数字0不相等,条件不成立,脚本输出no。 - 不带双引号的情况(jpg2.sh):Shell会对命令替换的结果执行单词拆分(word splitting),自动忽略前导/尾随的空白字符,所以
0会被处理成纯0,判断条件变成[ 0 = 0 ],条件成立,脚本输出yes。
从set -x的日志验证
你添加的set -x调试日志把这个差异展示得明明白白:
jpg1.sh的日志:+ '[' ' 0' = 0 ']'→ 带空格的字符串和0做比较jpg2.sh的日志:+ '[' 0 = 0 ']'→ 去掉空格后的数值和0做比较
题外话:更靠谱的文件存在判断方式
其实用ls *.jpg | wc -l来判断文件存在与否不是最佳实践——ls的错误输出会干扰,而且如果文件名包含空格或特殊字符也容易出问题。更稳妥的写法可以用:
if compgen -G "*.jpg" > /dev/null; then echo "no" else echo "yes" fi
或者借助通配符和数组:
shopt -s nullglob files=(*.jpg) if [ ${#files[@]} -eq 0 ]; then echo "yes" else echo "no" fi
内容的提问来源于stack exchange,提问作者aafulei
相关产品推荐
相关产品推荐

