bash의 조건식에서 -a와 -e의 차이점은 무엇입니까?


12

보낸 사람 man bash:

CONDITIONAL EXPRESSIONS
[...]
       -a file
              True if file exists.
[...]
       -e file
              True if file exists.
  1. 그렇다면 [ -a $FILE ]과 의 차이점은 무엇 [ -e $FILE ]입니까?
  2. 실제 차이가 없다면 같은 목적으로 두 개의 플래그가 존재하는 이유는 무엇입니까?

커뮤니티에 자신의 추론을 공유하지 않는 한 개발자 만 # 2를 알게됩니다.
벨민 페르난데스

답변:


13

에서 bash두 개의 인수의 컨텍스트는, test명령, -a file-e file동일합니다. 그러나 -a이진 연산자 이기 때문에 약간의 차이 가 있습니다.

-e단항은 POSIX에 의해 정의되지만 -a단항은 그렇지 않습니다. POSIX는 -a바이너리 만 정의합니다 ( POSIX 테스트 참조 ).

POSIX는 다음과 같은 세 가지 인수 test동작을 정의합니다 .

3 가지 주장 :

  • $ 2가 이진 기본이면 $ 1 및 $ 3의 이진 테스트를 수행하십시오.

  • $ 1이 '!'이면 $ 2와 $ 3의 두 인수 인수 검정을 무효화합니다.

  • $ 1이 '('이고 $ 3이 ')'이면 단항 테스트 $ 2를 수행하십시오. XSI 옵션을 지원하지 않는 시스템에서 $ 1이 '('이고 $ 3이 ')'이면 결과가 지정되지 않습니다.

  • 그렇지 않으면 지정되지 않은 결과를 생성하십시오.

따라서 -a이상한 결과가 발생합니다.

$ [ ! -a . ] && echo true
true

-a세 개의 인수와 관련하여 이진 연산자로 간주됩니다. Bash FAQ 질문 E1을 참조하십시오 . POSIX는 -aKornShell에서 가져 왔지만 바이너리와 단항을 -e혼동 하기 때문에 나중에 변경되었습니다 .-a-a

C 쉘에서 제공하는 기능과 유사한 기능을 가진 -e primary가 추가되었습니다. 쉘 스크립트가 파일을 열려고하지 않고 파일이 존재하는지 확인할 수있는 유일한 방법을 제공하기 때문입니다. 구현시 추가 파일 유형을 추가 할 수 있으므로 이식 가능한 스크립트는 다음을 사용할 수 없습니다.

테스트 -b foo -o -c foo -o -d foo -o -f foo -o -p foo

foo가 기존 파일인지 확인합니다. 역사적인 BSD 시스템에서 파일의 존재는 다음에 의해 결정될 수 있습니다.

테스트 -f foo -o -d foo

그러나 기존 파일이 일반 파일인지 쉽게 확인할 수 없었습니다. 초기 제안에서는 KornShell (일차적 인 의미 (같은 의미))을 사용했지만 인간이 -a를 -a 이항 연산자와 혼동 할 가능성이 높기 때문에 -e로 변경되었습니다.

-a바이너리는 또한 모호한 표현으로 이어지기 때문에 4 개 이상의 인수를 갖기 때문에 더 이상 사용되지 않는 것으로 표시됩니다. 이러한> 4 인수 표현식을 사용하면 POSIX는 결과가 지정되지 않은 것으로 정의합니다.


알고 멋지다! 이제는 좀 더 명확합니다 :)!
polym

9

.1. 그렇다면 [-a $ FILE]과 [-e $ FILE]의 차이점은 무엇입니까?

전혀 차이가 없습니다.

라인에서 505-507test.cbash는 버전 4.2.45(1)-release:

case 'a':           /* file exists in the file system? */
case 'e':
  return (sh_stat (arg, &stat_buf) == 0);

이는 두 플래그 사이에 실제 차이가 없음을 나타냅니다.

.2. 실제 차이가 없다면 같은 목적으로 두 개의 플래그가 존재하는 이유는 무엇입니까?

gnouc 의 답변을 참조하십시오 .


3
주어진 반면, -a 떠들썩한 파티에서 부울 연산자 (과) 완전히 중복이 추가 의미를 추가하는 경향이 버그가 보인다; 다른 구현과의 호환성 및 / 또는 이전 버전과의 호환성과 관련이 있다고 생각합니다 -e.
celtschk

@celtschk - 그것은 bugprone 아니라, 쉘의 파서가 될 수있다. POSIX는에 -a-o부울을 지정합니다 [ test ]. 그러나 (와 같은 ) 일부 쉘 은 연산자와 인수를 구별하는 데 어려움을 겪었으며 결과는 신뢰할 수 없었습니다. POSIX는 모든 호환 쉘이 대괄호 내에서 최소한 4 개의 인수를 처리해야한다고 요구했습니다 . bash[ test ][ test ]
mikeserv

5

내가 찾은 가장 좋은 대답은 StackOverflow 질문에서 얻은 것입니다.

-a더 이상 사용되지 않으므로 맨 페이지에는 표시되지 /usr/bin/test않지만 bash에는 계속 표시됩니다. 사용하십시오 -e. 단일 '['의 경우 bash 내장은 bash 내장과 동일하게 test동작하며 이는 bash 내장 /usr/bin/[과 동일하게 작동합니다 /usr/bin/test (하나는 다른 것과의 심볼릭 링크입니다). 효과는 -a위치 에 따라 다릅니다 file exists. 시작 위치에있는 경우의 의미 입니다. 두 표현식의 중간에 있으면 logical을 의미 and합니다.

[ ! -a /path ] && echo exists그 밖에 수동 점 bash는 같이하지 작업을 수행 -a이항 연산자가 간주되며, 위의 있도록로서 해석되지 negate -a ..하지만 같은 if '!' and '/path' is true(비 비어 있음). 따라서 스크립트는 항상 "-a"(실제로는 파일을 테스트) 출력 "! -a"하며 실제로는 바이너리 and입니다.

를 들어 [[, -a바이너리로 사용되지 않습니다 and더 이상 ( &&그것의 유일한 목적은 파일을 확인하는 것입니다, 그래서이 사용된다)가 (사용되지 않지만). 따라서 부정은 실제로 당신이 기대하는 것을 수행합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.