Bedingtes Testen auf Existenz bestimmter Dateien und Dateitypen in zsh

Bedingtes Testen auf Existenz bestimmter Dateien und Dateitypen in zsh

abcIch möchte das aktuelle Verzeichnis auf das Vorhandensein von Dateien mit den Erweiterungen , bakoder 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.

  • Nals Glob-Qualifizierer wird für diesen Glob aktiviert nullglob(bewirkt, dass der Glob auf nichts erweitert wird, wenn er keiner Datei entspricht)

  • Y1begrenzt 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 zshmacht 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 -nwir dabei nur prüfen, ob die Globs übereinstimmen, nicht, ob es sich bei den entsprechenden Dateien um normale Dateien handelt).

verwandte Informationen