Quiero verificar en el directorio actual la existencia de archivos con extensiones de abc
, bak
o tmp
,oun archivo llamado tmpout.wrk
. No puedo hacer que esto (eventualmente parte de una función) funcione en zsh. Se ejecuta, pero no lo detecta correctamente.
if [[ -f *.(abc|bak|tmp) || -f tmpout.wrk ]]; then
echo 'true';
else
echo 'false';
fi
Respuesta1
Para probar que el globo devuelve al menos un archivo, puedes hacer:
if ()(($#)) (*.(abc|bak|tmp)|tmpout.wrk)(NY1); then
echo true
else
echo false
fi
Para comprobar que al menos uno de ellos es un archivo normal después de la resolución del enlace simbólico, agregue el -.
calificador global:
if ()(($#)) (*.(abc|bak|tmp)|tmpout.wrk)(NY1-.); then
echo true
else
echo false
fi
()(($#))
Es una función anónima a la que le pasamos el resultado de los globos. El cuerpo de esa función ((($#))
) simplemente prueba que el número de argumentos sea distinto de cero.N
cuando se activa un calificador globalnullglob
para ese global (hace que el global se expanda a nada cuando no coincide con ningún archivo)Y1
limita la expansión a como máximo un archivo. Es una optimización del rendimiento.-
hace que se considere el próximo clasificado globaldespuésresolución de enlace simbólico..
considera solo archivos normales (por lo que aquí los archivos normales o enlaces simbólicos eventualmente se resuelven en un archivo normal, como[ -f file ]
lo hace el comando).
Respuesta2
TL;DR
set -o extendedglob
if [[ -n *.(abc|bak|tmp)(#qN) || -f tmpout.wrk ]]; then
De lo contrario, mediante algunas pruebas,
% [[ -f /etc/passwd ]] && echo yea
yea
% echo /etc/passw?
/etc/passwd
% [[ -f /etc/passw? ]] && echo yea
%
Bien, ¿qué está zsh
haciendo aquí?
% set -x
% [[ -f /etc/passw? ]] && echo yes
+zsh:13> [[ -f '/etc/passw?' ]]
%
Esas comillas simples seguro que no van a incluir nada. Busquemos [[
en man zshall
... y luego busquemos en CONDITIONAL EXPRESSIONS
... ah, aquí hay algo sobre la generación de nombres de archivos:
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.
Entonces, con esto en mente,
% [[ -f /etc/passw?(#q) ]] && echo yes
+zsh:14> [[ -f /etc/passwd ]]
+zsh:14> echo yes
yes
% exec zsh -l
Y a su caso, contabilizando el caso en el que puede que no existan expedientes:
% 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
%
(aunque con -n
solo verificamos que los globos coincidan, no que los archivos correspondientes sean archivos normales).