既然我当前工作目录下没有jpg
文件,为什么jpg1.sh
和jpg2.sh
这两个脚本给不同的结果?如何理解差异?请注意,脚本之间的唯一区别是是否在 $()
命令替换周围使用双引号。
$ cat jpg1.sh
#!/bin/bash
if [ "$(ls *.jpg | wc -l)" = 0 ]; then
echo "yes"
else
echo "no"
fi
$ ./jpg1.sh
ls: *.jpg: No such file or directory
no
$ cat jpg2.sh
#!/bin/bash
if [ $(ls *.jpg | wc -l) = 0 ]; then
echo "yes"
else
echo "no"
fi
$ ./jpg2.sh
ls: *.jpg: No such file or directory
yes
跟进
我证明打勾的答案是切中要害的——wc -l
的返回值中有一些额外的空格。将 set -x
添加到两个脚本后,差异就显而易见了。
$ ./jpg1.sh
++ wc -l
++ ls '*.jpg'
ls: *.jpg: No such file or directory
+ '[' ' 0' = 0 ']'
+ echo no
no
$ ./jpg2.sh
++ wc -l
++ ls '*.jpg'
ls: *.jpg: No such file or directory
+ '[' 0 = 0 ']'
+ echo yes
yes
顺便说一句,我的系统是 macOS Catalina。
最佳答案
在某些系统上这是错误的,因为 wc -l
用空格填充它的答案,而你正在比较的字符串 -- 0
-- 不包含任何空格。当您使用引号时,会比较确切的输出;当您将它们关闭时,输出会根据空格分成单独的单词,并且每个单词都会扩展为一个 glob,然后再将其放入 [
命令行。要确定您是否在这样的系统上,请将 set -x
添加到您的脚本以启用跟踪级日志记录,这样您就可以看到 [
被要求的确切值比较。
在目前的情况下,整个问题都被简单地避免了:没有理由为此目的使用 either ls
或 wc
。
#!/usr/bin/env bash
shopt -s nullglob
jpegs=( *.jpg )
if (( ${#jpegs[@]} == 0 )); then
echo "No JPEG files were found"
else
echo "Exactly ${#jpegs[@]} JPEG files were found"
fi
关于bash - 除非删除引号,否则为什么 [ "$(ls *.jpg | wc -l)"= 0 ] 总是假的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64429628/