abc
Ich möchte das aktuelle Verzeichnis auf das Vorhandensein von Dateien mit den Erweiterungen , bak
oder tmp
, überprüfen .odereine Datei namens tmpout.wrk
. Ich kann dies (eventuell Teil einer Funktion) in zsh nicht zum Laufen bringen. Es läuft, wird aber nicht richtig erkannt.
if [[ -f *.(abc|bak|tmp) || -f tmpout.wrk ]]; then
echo 'true';
else
echo 'false';
fi
Antwort1
Um zu testen, ob der Glob mindestens eine Datei zurückgibt, können Sie Folgendes tun:
if ()(($#)) (*.(abc|bak|tmp)|tmpout.wrk)(NY1); then
echo true
else
echo false
fi
Um zu überprüfen, ob mindestens eine davon nach der Symlink-Auflösung eine reguläre Datei ist, fügen Sie den -.
Glob-Qualifizierer hinzu:
if ()(($#)) (*.(abc|bak|tmp)|tmpout.wrk)(NY1-.); then
echo true
else
echo false
fi
()(($#))
ist eine anonyme Funktion, an die wir das Ergebnis der Globs übergeben. Der Hauptteil dieser Funktion ((($#))
) prüft lediglich, ob die Anzahl der Argumente ungleich Null ist.N
als Glob-Qualifizierer wird für diesen Glob aktiviertnullglob
(bewirkt, dass der Glob auf nichts erweitert wird, wenn er keiner Datei entspricht)Y1
begrenzt die Erweiterung auf höchstens eine Datei. Es handelt sich um eine Leistungsoptimierung.-
macht den nächsten Glob-Qualifikator berücksichtignachSymlink-Auflösung..
berücksichtigt nur reguläre Dateien (also hier reguläre Dateien oder symbolische Links, die letztendlich in eine reguläre Datei aufgelöst werden, wie es der[ -f file ]
Befehl tut).
Antwort2
Kurz zusammengefasst
set -o extendedglob
if [[ -n *.(abc|bak|tmp)(#qN) || -f tmpout.wrk ]]; then
Andernfalls, durch einige Tests,
% [[ -f /etc/passwd ]] && echo yea
yea
% echo /etc/passw?
/etc/passwd
% [[ -f /etc/passw? ]] && echo yea
%
Ok, was zsh
macht du hier?
% set -x
% [[ -f /etc/passw? ]] && echo yes
+zsh:13> [[ -f '/etc/passw?' ]]
%
Mit diesen einfachen Anführungszeichen lässt sich sicher nichts erreichen. Suchen wir weiter [[
in man zshall
... und dann weiter CONDITIONAL EXPRESSIONS
... ah, hier ist etwas zur Dateinamengenerierung:
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.
Vor diesem Hintergrund
% [[ -f /etc/passw?(#q) ]] && echo yes
+zsh:14> [[ -f /etc/passwd ]]
+zsh:14> echo yes
yes
% exec zsh -l
Und zu Ihrem Fall, für den Fall, dass möglicherweise keine Dateien vorhanden sind:
% 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
%
(wobei -n
wir dabei nur prüfen, ob die Globs übereinstimmen, nicht, ob es sich bei den entsprechenden Dateien um normale Dateien handelt).