Shell-Script
zsh 中是否存在特定文件和文件類型的條件測試
我想檢查目前目錄是否存在副檔名為*、 或 或*
abc
名為bak
的tmp
文件的文件。我無法讓這個(最終是函式的一部分)在 zsh 中工作。它執行,但無法正確檢測。tmpout.wrk
if [[ -f *.(abc|bak|tmp) || -f tmpout.wrk ]]; then echo 'true'; else echo 'false'; fi
TL;博士
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 是否匹配,而不是相應的文件是正常文件)。
要測試 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 ]
命令一樣)。