이 문제를 해결하려면 glob이 /a/b/c/*
일치하는 항목을 생성하지 않는다고 가정합니다.
이는 다음 테스트가 실패해야 함을 의미합니다(즉, 0이 아닌 값을 생성해야 함 $?
).
[[ -n /a/b/c/*(#qN) ]]
실제로 이런 경우가 있습니다만약에(zsh) 명령줄에서 직접 테스트를 실행합니다. 하지만 내가 계속한다면완전 똑같은 테스트스크립트에서는 예상되는 동작이 아닌 성공합니다.
해당 플래그를 사용하여 동일한 스크립트를 실행하면 -x
결과 추적에 테스트가 다음과 같이 표시됩니다.
[[ -n '/a/b/c/*(#qN)' ]]
테스트 매개변수 주위에 작은 따옴표가 나타나는 이유를 이해할 수 없습니다. 스크립트 소스 코드에는 따옴표가 전혀 없습니다.
zsh가 이러한 작은따옴표를 자동으로 삽입하면 텍스트가 성공한 이유가 설명됩니다.
질문:
- 이 표현식의 명령줄 버전과 스크립트 버전 간에 차이가 있는 이유는 무엇입니까?
- 스크립트의 테스트가 (올바르게) 실패하도록 하려면 어떻게 해야 합니까?
답변1
CONDITIONAL EXPRESSIONS
zsh 매뉴얼 의 섹션:
어떤 형태의 조건부 인수에서도 파일 이름 생성이 수행되지 않습니다. 그러나 일반 셸 확장이 적용되고 EXTENDED_GLOB 옵션이 적용되는 경우 문자열 끝에 (#q) 형식의 명시적 glob 한정자를 사용하여 이를 강제로 적용할 수 있습니다.
즉, 스크립트 내에서 extendedglob
옵션이 설정되지 않은 경우 /a/b/c/*(#qN)
리터럴 문자열로 처리됩니다.
답변2
glob이 파일과 일치하는지 확인하는 더 나은 관용구(IMO)는 다음과 같습니다.
()(($#)) /a/b/c/*(NY1)
extendedglob
여기에는 특별한 상황이 필요하지 않습니다 [[ -n ...(#qN) ]]
. 그리고 Y1
첫 번째 플레이에서 멈추기 때문에 더 효율적입니다.
(($#))
이는 익명 함수에 인수 수가 0이 아닌 경우 true를 반환하는 산술 표현식 인 익명 함수에 glob 확장을 전달하는 방식으로 작동합니다 .
이를 다음과 같이 확장할 수 있습니다.
if ()(( $# >= 3 )) /a/b/c*(NY3); then
echo there were at least 3 matching files.
fi