나는 이것을 이해하지 못한다:
스크립트:WORKDIR/sh/script.sh
[ -e filename ] \
&& echo filename \
|| [ -e ../filename ] \
&& echo ../filename \
|| { echo 'ERROR: failed to find "filename"' 1>&2 ; exit -1; }
산출:
$ cd WORKDIR/sh
$ ./script.sh
../filename
$ cd WORKDIR
$ sh/script.sh
filename
../filename # <---- WHY????
내 생각:
1
[ -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; }
2
[ -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; }
버전:
bash --version
GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)
답변1
&&
||
우선순위가 동일하므로 다음과 같습니다 .
명령이 들어오면 &&
바로 인접한 연산자가 아니더라도 다음 명령을 찾아 실행합니다. 당신은해야안 돼요단일 명령 목록에서 이러한 연산자를 여러 개 사용하십시오. 둘 이상이 필요한 경우 if/then 구조를 사용할 수 있습니다.
$ true && true || echo yes && echo no
no
이는 다음과 매우 다릅니다.
if true; then
true
else
echo yes && echo no
fi
$ if true; then true; else echo yes && echo no; fi
$
또는:
$ true && false || echo yes && echo no
yes
no
$ if true; then false; else echo yes && echo no; fi
$
나는 당신의 구성을 다음과 같이 작성합니다 :
if [ -e filename ]; then
echo filename
elif [ -e ../filename ]; then
echo ../filename
else
echo 'ERROR: failed to find "filename"' >&2
exit -1
fi
답변2
나는 당신이 bash가 이것을 하기를 원한다고 생각합니다:
(A && B) || (C && D) || E
하지만 실제로는 이렇게 됩니다
(A && B || C) && D || E
여기서 D는 다음과 같이 실행됩니다.누구나B 또는 C가 성공합니다.
그룹을 더 추가하세요.
[ -e filename ] && echo filename || {
[ -e ../filename ] && echo ../filename || {
echo 'ERROR: failed to find "filename"' 1>&2
exit -1
}
}
또는
{ [ -e filename ] && echo filename ; } ||
{ [ -e ../filename ] && echo ../filename; } ||
{ echo 'ERROR: failed to find "filename"' 1>&2 ; exit -1; }
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
파일 이름은 상위 디렉터리에 있습니다.
[ -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