我正在testing一个简单的脚本,我想知道为什么它从目录执行时工作正常: ./test.sh但是当我尝试使用“sh”命令sh test.sh它不工作:
test.sh: 3: test.sh: [[: not found test.sh: 7: test.sh: [[: not found
脚本:
#!/usr/bin/env bash if [[ $1 = one ]] then printf "%b" "two\n" >&2 exit 0 elif [[ $1 = two ]] then printf "%b" "one\n" >&2 exit 0 else printf "%b" "Specify argument: one/two\n" exit 1 fi
sh是与bash不同的程序。
问题是Bourne Shell( sh )不是Bourne Again shell( bash )。 即sh不理解[[ pragma。 事实上,它也不明白。 [是/ bin / test(或/ usr / bin / [,/ usr / bin / test))的实际程序或链接。
$ which [ /bin/[ $ ls -lh /bin/[ -r-xr-xr-x 2 root wheel 42K Feb 29 17:11 /bin/[
当您通过./test.sh直接执行脚本时,您将脚本作为第一行指定程序的第一个参数。 在这种情况下:
#!/usr/bin/env bash
通常,这是直接的解释器( /bin/bash ,或其他任何脚本解释器),但在你的情况下,你正在使用env在修改后的环境中运行一个程序 – 但后面的参数仍然是bash。 有效地,./ bash test.sh是bash test.sh ./test.sh
因为sh和bash是不同的语法解释不同的shell,你会看到这个错误。 如果你运行bash test.sh ,你应该看到预期的结果。
其他人在评论中指出, /bin/sh可以是链接或其他shell。 历史上, sh是旧AT&T Unix上的Bourne shell,在我看来是规范的下降。 然而,这在BSD的变化中是不同的,并且在其他基于Unix的系统和发行版中随着时间的推移已经发生了变化。 如果您真的对内部工作感兴趣(包括/ bin / sh和/ bin / bash可以是相同的程序,而且行为完全不同),请阅读以下内容:
超级用户:bash和sh有什么区别
维基百科:Bourne shell
如上所述:/ bin / sh通常(尽pipe不总是)调用符合POSIX标准的Bourne shell。 Bash不是Bourne。
Bash在尝试模仿Bourne(当/ sh / sh符号链接或链接到/ bin / bash时),或者在调用环境中定义$ POSIXLY_CORRECT时,使用–posix调用选项调用时,或者当'set -o posix'被执行时。 这可以testingBourne shell脚本/命令是否符合POSIX标准。
或者,使用已知的POSIX兼容shell调用脚本/testing命令。 'dash'很接近,Korn shell(ksh)IIRC也提供了符合POSIX标准的选项。