我不明白这个:
脚本: WORKDIR/sh/script.sh
[ -e filename ] \
&& echo filename \
|| [ -e ../filename ] \
&& echo ../filename \
|| { echo 'ERROR: failed to find "filename"' 1>&2 ; exit -1; }
Run Code Online (Sandbox Code Playgroud)
输出:
$ cd WORKDIR/sh
$ ./script.sh
../filename
$ cd WORKDIR
$ sh/script.sh
filename
../filename # <---- WHY????
Run Code Online (Sandbox Code Playgroud)
我的想法:
[ -e filename ] \ -> false
&& -> skip this, it is already false
echo filename \ -> don't even try
|| [ -e ../filename ] \ -> true
&& echo ../filename \ -> true
|| -> already true, skip the rest
{ echo 'ERROR: failed to find "filename"' 1>&2 ; exit -1; }
Run Code Online (Sandbox Code Playgroud)
[ -e filename ] \ -> true
&& echo filename \ -> true
|| -> already true, skip the rest
[ -e ../filename ] \
&& echo ../filename \
|| { echo 'ERROR: failed to find "filename"' 1>&2 ; exit -1; }
Run Code Online (Sandbox Code Playgroud)
版本:
bash --version
GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)
Run Code Online (Sandbox Code Playgroud)
&&并||具有相同的优先级,因此:
当一个命令通过时,它会寻找下一个&&并执行它,即使它不是直接相邻的操作符。您永远不应在单个命令列表中使用多个这些运算符。如果需要多个,则使用 if/then 构造。
$ true && true || echo yes && echo no
no
Run Code Online (Sandbox Code Playgroud)
这与以下非常不同:
if true; then
true
else
echo yes && echo no
fi
Run Code Online (Sandbox Code Playgroud)
$ if true; then true; else echo yes && echo no; fi
$
Run Code Online (Sandbox Code Playgroud)
或者:
$ true && false || echo yes && echo no
yes
no
$ if true; then false; else echo yes && echo no; fi
$
Run Code Online (Sandbox Code Playgroud)
我会把你的构造写成:
if [ -e filename ]; then
echo filename
elif [ -e ../filename ]; then
echo ../filename
else
echo 'ERROR: failed to find "filename"' >&2
exit -1
fi
Run Code Online (Sandbox Code Playgroud)
我认为您希望 bash 这样做:
(A && B) || (C && D) || E
Run Code Online (Sandbox Code Playgroud)
但它实际上是这样做的
(A && B || C) && D || E
Run Code Online (Sandbox Code Playgroud)
其中d执行,如果任一B或C成功。
添加更多分组:
(A && B) || (C && D) || E
Run Code Online (Sandbox Code Playgroud)
或者
(A && B || C) && D || E
Run Code Online (Sandbox Code Playgroud)
或者使用if-elif-else@Jesse_b 展示的非常清晰易读的风格。
一步一步,这正在发生:
文件名在当前目录中:
[ -e filename ] \ # test succeeds, status is now 0
&& # status is zero, will execute this branch
echo filename \ # echo succeeds, status is now 0
|| # status is zero, do not execute
[ -e ../filename ] \ # not executed
&& # status is zero, will execute this branch
echo ../filename \ # echo succeeds, status is now 0
|| # status is zero, do not execute
{ echo; exit; } # not executed
Run Code Online (Sandbox Code Playgroud)文件名在父目录中:
[ -e filename ] \ # test fails, status is now 1
&& # status is non-zero, do not execute this branch
echo filename \ # not executed
|| # status is non-zero, will execute this branch
[ -e ../filename ] \ # test succeeds, status is now 0
&& # status is zero, will execute this branch
echo ../filename \ # echo succeeds, status is now 0
|| # status is zero, do not execute
{ echo; exit; } # not executed
Run Code Online (Sandbox Code Playgroud)