파일 이름 생성이 실패하면 zsh가 스크립트 처리를 중지하는 이유는 무엇입니까?

파일 이름 생성이 실패하면 zsh가 스크립트 처리를 중지하는 이유는 무엇입니까?

나는 다음에서 발견된 모든 실행 가능한 프로그램을 작성하기 위한 짧은 스크립트를 작성하려고 합니다 $PATH.

for dir in $(tr ':' ' ' <<<"${PATH}"); do
  for pgm in $dir/*; do
    if command -v "${pgm}" >/dev/null 2>&1; then
      echo "${pgm}"
    fi
  done
done | sort >file

Bash에서는 예상대로 작동하지만 내부 루프에서 파일 이름 생성이 실패하면 zsh는 스크립트 처리를 중지합니다.

for pgm in $dir/*; do
           ^^^^^^
  ...
done

결과적으로 my에는 $PATH파일( )이 포함되지 않은 디렉터리가 포함되어 있으므로 /usr/local/sbinzsh에서 스크립트는 나중에 디렉터리에서 발견된 실행 파일에 쓸 수 없습니다.

동일한 문제를 보여주는 또 다른 코드는 다음과 같습니다.

for f in /not_a_dir/*; do
  echo 'in the loop'
done
echo 'after the loop'

Bash에서 이 명령은 다음을 출력합니다.

in the loop
after the loop

코드를 사용하여 종료합니다 0.

zsh에서는 동일한 명령이 출력됩니다.

no matches found: /not_a_dir/*

코드를 사용하여 종료합니다 1.

쉘 간의 동작 차이는 nomatch아래 설명된 대로 options 에서 비롯되는 것 같습니다 man zshoptions.

일치하지 않음(+3) <C> <Z>

파일 이름 생성 패턴과 일치하는 항목이 없으면 인수 목록에 변경하지 않고 그대로 두는 대신 오류가 인쇄됩니다. 이는 초기 ~또는 에도 적용됩니다 =.

man zshexpn(파일 이름 생성 섹션)에 설명되어 있습니다 .

해당 단어는 패턴과 일치하는 정렬된 파일 이름 목록으로 대체됩니다. 일치하는 패턴이 발견되지 않으면 NULL_GLOB 옵션이 설정되어 단어가 제거되거나 NOMATCH 옵션이 설정 해제되어 단어가 변경되지 않는 한 쉘은 오류 메시지를 표시합니다.

설정을 해제하면 nomatchzsh는 bash처럼 동작합니다.

unsetopt nomatch
for f in /not_a_dir/*; do
  echo 'in the loop'
done
echo 'after the loop'

이제 bash와 zsh의 동작 차이와 스크립트가 zsh에서 오류를 발생시키는 이유를 이해하지만 파일 이름 생성이 실패하면 zsh가 스크립트 처리를 즉시 중지하는 이유를 이해하고 싶습니다. 그래서 실패한 파일 이름 생성을 실패한 명령으로 대체하여 동일한 문제를 (실행을 통해) 재현하려고 했습니다 not_a_cmd.

for f in ~/*; do
  not_a_cmd
done
echo 'after the loop'

그러나 스크립트의 출력은 두 셸에서 거의 동일합니다(로 인한 오류 메시지 제외 not_a_cmd). 특히 두 쉘 모두 다음을 인쇄합니다.

after the loop

두 쉘 모두 코드로 종료됩니다 0.

실패한 파일 이름 생성(예: for f in /not_a_dir/*)으로 인해 zsh가 스크립트 처리를 중지하지만 실패한 명령(예 not_a_cmd: )은 중지되지 않는 이유는 무엇입니까?

나는 그것을 사용하고 있습니다 zsh 5.6.2-dev-0 (x86_64-pc-linux-gnu).

답변1

이는 버그가 아닌 기능입니다.

관련 정보