![zsh의 특정 파일 및 파일 유형 존재에 대한 조건부 테스트](https://linux55.com/image/122700/zsh%EC%9D%98%20%ED%8A%B9%EC%A0%95%20%ED%8C%8C%EC%9D%BC%20%EB%B0%8F%20%ED%8C%8C%EC%9D%BC%20%EC%9C%A0%ED%98%95%20%EC%A1%B4%EC%9E%AC%EC%97%90%20%EB%8C%80%ED%95%9C%20%EC%A1%B0%EA%B1%B4%EB%B6%80%20%ED%85%8C%EC%8A%A4%ED%8A%B8.png)
abc
현재 디렉터리에 확장자가 또는 bak
인 파일이 있는지 확인하고 싶습니다 tmp
.또는이라는 함수 tmpout.wrk
는 zsh에서 작동하도록(결국 함수의 일부임) 얻을 수 없습니다. 작동하지만 올바르게 감지하지 못합니다.
if [[ -f *.(abc|bak|tmp) || -f tmpout.wrk ]]; then
echo 'true';
else
echo 'false';
fi
답변1
glob이 하나 이상의 파일을 반환하는지 테스트하려면 다음을 수행할 수 있습니다.
if ()(($#)) (*.(abc|bak|tmp)|tmpout.wrk)(NY1); then
echo true
else
echo false
fi
확인된 심볼릭 링크 중 하나 이상이 일반 파일인지 확인하려면 -.
glob 한정자를 추가하세요.
if ()(($#)) (*.(abc|bak|tmp)|tmpout.wrk)(NY1-.); then
echo true
else
echo false
fi
()(($#))
glob의 결과를 전달하는 익명 함수입니다. 함수의 본문((($#))
)은 단순히 인수 개수가 0이 아닌지 테스트합니다.N
이 glob의 glob 한정자로 엽니다nullglob
(glob이 어떤 파일과도 일치하지 않으면 glob을 아무것도 확장하지 않게 만듭니다).Y1
확장은 최대 1개의 파일로 제한됩니다. 이는 성능 최적화입니다.-
다음 glob 한정자를 고려하게 합니다.뒤쪽에심볼릭 링크 해결..
일반 파일만 고려됩니다(따라서 이 일반 파일 또는 심볼릭 링크는 결국 명령과 마찬가지로 일반 파일로 확인됩니다[ -f file ]
).
답변2
긴 이야기 짧게
set -o extendedglob
if [[ -n *.(abc|bak|tmp)(#qN) || -f tmpout.wrk ]]; then
그렇지 않으면 몇 가지 테스트를 통해
% [[ -f /etc/passwd ]] && echo yea
yea
% echo /etc/passw?
/etc/passwd
% [[ -f /etc/passw? ]] && echo yea
%
알았어, zsh
여기서 뭐 하는 거야?
% set -x
% [[ -f /etc/passw? ]] && echo yes
+zsh:13> [[ -f '/etc/passw?' ]]
%
작은 따옴표는 확실히 결과를 생성하지 않습니다. [[
... 을 검색 man zshall
한 다음 ...을 검색해 보겠습니다 CONDITIONAL EXPRESSIONS
. 아, 파일 이름 생성에 대한 내용은 다음과 같습니다.
Filename generation is not performed on any form of argument to condi-
tions. However, it can be forced in any case where normal shell expan-
sion is valid and when the option EXTENDED_GLOB is in effect by using
an explicit glob qualifier of the form (#q) at the end of the string.
A normal glob qualifier expression may appear between the `q' and the
closing parenthesis; if none appears the expression has no effect
beyond causing filename generation. The results of filename generation
are joined together to form a single word, as with the results of other
forms of expansion.
This special use of filename generation is only available with the [[
syntax. If the condition occurs within the [ or test builtin commands
then globbing occurs instead as part of normal command line expansion
before the condition is evaluated. In this case it may generate multi-
ple words which are likely to confuse the syntax of the test command.
For example,
[[ -n file*(#qN) ]]
produces status zero if and only if there is at least one file in the
current directory beginning with the string `file'. The globbing qual-
ifier N ensures that the expression is empty if there is no matching
file.
그래서 그 점을 염두에 두고,
% [[ -f /etc/passw?(#q) ]] && echo yes
+zsh:14> [[ -f /etc/passwd ]]
+zsh:14> echo yes
yes
% exec zsh -l
귀하의 경우 파일이 없는 경우를 고려하십시오.
% mkdir dir
% cd dir
% touch blah.foo
% [[ -f *.(foo|bar|baz)(#q) ]] && echo yea
yea
% rm blah.foo
% [[ -f *.(foo|bar|baz)(#q) ]] && echo yea
zsh: no matches found: *.(foo|bar|baz)(#q)
% [[ -f *.(foo|bar|baz)(#qN) ]] && echo yea
% touch a.foo b.foo
% [[ -f *.(foo|bar|baz)(#qN) ]] && echo yea
% [[ -n *.(foo|bar|baz)(#qN) ]] && echo yea
yea
%
( -n
글로브가 일치하는지 여부만 확인하지만 해당 파일이 일반 파일인지 여부는 확인하지 않습니다.)