1

1

나는 이것을 이해하지 못한다:

스크립트: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가 시연한 매우 명확하고 읽기 쉬운 스타일을 사용하세요.


단계별로 이런 일이 일어나고 있습니다.

  1. 파일 이름은 현재 디렉터리에 있습니다.

    [ -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
    
  2. 파일 이름은 상위 디렉터리에 있습니다.

    [ -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
    

관련 정보