if 문에서 리디렉션을 사용하거나 파일에 쓰는 것이 종료 코드에 어떻게 그리고 왜 영향을 미치나요?

if 문에서 리디렉션을 사용하거나 파일에 쓰는 것이 종료 코드에 어떻게 그리고 왜 영향을 미치나요?

존재하다다루기 힘든

echo 'a string' > test.txt
echo $?
0

그리고

[[ $(echo 'a string') ]]
echo $?
0

하지만

[[ $(echo 'a string' > test.txt) ]]
echo $?
1

다른 예시

curl -so 'curl-8.2.1.tar.gz' https://curl.se/download/curl-8.2.1.tar.gz
echo $?
0

또는

[[ $(curl -so 'curl-8.2.1.tar.gz' https://curl.se/download/curl-8.2.1.tar.gz) ]]
echo $?
1

내 질문:

  1. 출력 리디렉션 때문인가요? 그렇지 않다면 그 이유는 무엇입니까?
  2. 명령 실행이 성공했습니다. a string나타나고 test.txt컬이 내가 지정한 출력 파일에 파일을 다운로드합니다. 평가 결과는 왜 나타납니까 false?
  3. 스크립트에서 이를 처리할 수 있는 합리적인 방법이 있습니까? 특정 명령을 실행하고 싶다고 가정해 보겠습니다. 이전 명령이 성공적으로 실행되었지만 false여전히 반환되는 경우 어떻게 실행해야 합니까? 해당 줄이 나타나는지 또는 파일이 다운로드되었는지 확인하기 위해 두 번째 검사를 추가할 수 있지만 처음에 명령이 성공적으로 실행되었는지 평가할 필요는 없습니다.

추가 완전성 예(가독성 대 "정확성"?):

if ( $(echo 'a string' > text.txt) ); then echo yes; else echo no;fi
yes
if (( $(echo 'a string' > text.txt) )); then echo yes; else echo no;fi
no
if $(echo 'a string' > text.txt); then echo yes; else echo no;fi
yes
if echo 'a string' > text.txt; then echo yes; else echo no;fi
yes

답변1

$?

내부에쉘에 의해 설정된 매개변수man 부분 zshparam, 즉 info zsh 'Parameters Set By The Shell' 여러분이 보게 될 것은 $?마지막 명령에 의해 반환된 종료 상태입니다.

$(...)

사람 에서는 zshexpn다음 info zsh 'Command Substitution'을 볼 수 있습니다.

명령 대체

'$(...)'괄호로 묶이고 앞에 달러 기호(예: )가 있거나 악센트로 인용된 명령(예: )은 ...후행 개행 문자가 제거된 표준 출력으로 대체됩니다.

예를 들어 표현식은 후행 개행 문자가 제거된 $(echo 'a string')명령( )의 출력으로 대체되어 가 됩니다 . 그러나 내부 명령은 표준 출력으로 출력을 생성하지 않으므로 표현식의 결과는 빈 문자열입니다.a string<newline>a string$(echo 'a string' > test.txt)

[[ ... ]]

zshmisc또는 맨 페이지에 info zsh 'Conditional Expressions'다음이 표시됩니다.

조건식

조건식은 복합 명령과 함께 사용되어 [[파일 속성을 테스트하고 문자열을 비교합니다. 각 표현식은 다음 단항 또는 이진 표현식 중 하나 이상으로 구성될 수 있습니다.

[...]

호환성을 위해 구문상 중요하지 않은 인수(일반적으로 변수)가 있는 경우 조건은 다음과 같이 처리됩니다. 식이 0이 아닌 문자열로 확장되는지 여부를 테스트합니다.

이제 예를 들어보자

따라서 다음 줄에서 명령의 출력 $( ... )은 string a string<newline>이므로 자체 확장자는 길이가 0이 아닌 문자열인 이므로 $(...)계산 은 true(0 종료 상태)를 반환합니다.a string[[ ... ]]

[[ $(echo 'a string') ]]

그러나 다음 명령에서는 리디렉션했기 때문에 확장은 $( ... )길이가 0인 문자열이 되고 [[ ... ]]계산은 false(0이 아닌 숫자인 종료 상태 1)를 반환합니다.

[[ $(echo 'a string' > test.txt) ]]

마찬가지로 다음 명령의 종료 상태는 curl이 명령의 종료 상태입니다.

curl -so 'curl-8.2.1.tar.gz' https://curl.se/download/curl-8.2.1.tar.gz

will 맨페이지 curl에서는 0이 아닌(실패) 종료 상태를 반환하는 조건을 설명합니다.

그러나 다음 예에서 종료 상태는 curl명령에 출력이 있는지(성공) 또는 출력이 없는지(실패)에 따라 달라집니다.

[[ $(curl -so 'curl-8.2.1.tar.gz' https://curl.se/download/curl-8.2.1.tar.gz) ]]

(( ... ))여기서 멈추겠습니다. 하지만 설명서를 계속 읽어도 됩니다.산술 평가사람의 일부 zshmisc(또는 info zsh 'Arithmetic Evaluation')

답변2

[[ ... ]]성공적인 명령 실행이 명령의 출력 결과가 0이 아닌 문자열이 되는 방식으로 이해되지 않는 한, using은 성공적인 명령 실행을 평가하는 데 적합하지 않다는 결론을 내립니다 . zsh 스크립트에서 확인하는 경우 올바른 방법은 다음과 같습니다.

  1. if command; then ...; [else ...;] fi(muru의 설명에 설명된 대로 사용됨)
  2. 명령을 단독으로 실행하고 $?나중에 종료 코드를 확인하십시오. 및/또는
  3. 예를 들어 생성된 파일의 내용을 검사하여 명령의 실제 출력을 확인합니다.

관련 정보