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

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

에서 man bash:

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

답변1

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세 인수의 맥락에서 이항 연산자로 처리됩니다. 바라보다배쉬 FAQ 문제 E1. POSIX에서는 KornShell에서 가져오는 것에 대해서도 언급했지만 바이너리와 단항을 혼동했기 때문에 -a나중에 변경되었습니다 .-e-a-a

기본 -e를 추가하면 파일을 열려고 하지 않고 파일이 존재하는지 여부를 알아내는 쉘 스크립트에 대한 유일한 방법을 제공한다는 점에서 C 쉘에서 제공하는 것과 유사한 기능을 갖습니다. 구현 시 추가 파일 형식을 추가할 수 있으므로 이식 가능한 스크립트를 사용할 수 없습니다.

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

foo가 기존 파일인지 확인합니다. 과거 BSD 시스템에서 파일의 존재는 다음을 통해 확인할 수 있습니다.

테스트 -f foo -o -d foo

그러나 기존 파일이 일반 파일인지 쉽게 확인할 수 있는 방법은 없습니다. 초기 제안에서는 KornShell -a 기본 연산자(동일한 의미를 가짐)를 사용했지만 사람들이 -a 기본 연산자와 -a 이진 연산자를 혼동할 수 있다는 우려 때문에 나중에 -e로 변경했습니다.

-a또한 바이너리는 4개 이상의 인수가 포함된 일부 모호한 표현식이 생성되므로 더 이상 사용되지 않는 것으로 표시됩니다. 이러한 4개 이상의 인수 표현식의 경우 POSIX는 결과를 지정되지 않도록 정의합니다.

답변2

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

전혀 차이가 없습니다.

배쉬 버전에서 505-507:test.c4.2.45(1)-release

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

이는 두 플래그 사이에 실제 차이가 없음을 보여줍니다.

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

바라보다cuonglm의 답변.

답변3

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

-a더 이상 사용되지 않으므로 더 이상 맨페이지에 나열되지 않지만 /usr/bin/testbash 맨페이지에는 계속 나열됩니다. 사용 -e. 단일 "["의 경우 bash 내장 기능은 bash 내장 기능과 동일하게 작동하며 이는 testand와 동일하게 작동합니다(하나는 다른 하나에 대한 심볼릭 링크입니다). 효과는 위치에 따라 달라집니다. 시작 부분에 있으면 의미합니다. 두 표현식의 중간에 있으면 논리를 나타냅니다./usr/bin/[/usr/bin/test-afile existsand

[ ! -a /path ] && echo existsbash 매뉴얼에서 지적했듯이 작동하지 않습니다. -a이항 연산자로 간주되므로 위의 내용은 a로 구문 분석되지 않고 negate -a ..( if '!' and '/path' is truenull이 아닌)로 구문 분석됩니다. 따라서 스크립트는 항상 출력 "-a"(실제로는 테스트 파일)하며 여기서는 "! -a"실제로 바이너리 파일입니다 and.

for 는 [[-a이상 바이너리로 사용되지 않으므로 and( &&더 이상 사용되지 않지만) 고유한 목적은 거기에서 파일을 확인하는 것입니다. 따라서 부정은 실제로 예상한 대로 작동합니다.

관련 정보