我想檢查當前目錄中是否存在擴展名為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 的結果傳遞給它。此函數的主體 ((($#))
) 只是測試參數數量是否非零。N
作為該 glob 的 glob 限定符開啟nullglob
(當 glob 與任何檔案不符時,使 glob 擴展為空)Y1
限制最多擴充一個檔案。這是一個性能優化。-
使下一個 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
我們只檢查 glob 是否匹配,而不檢查相應的文件是否是常規文件)。