Creé un script para realizar algunas operaciones con archivos por mí. Estoy usando el operador comodín *
para aplicar funciones a todos los archivos de un tipo, pero hay una cosa que no entiendo. Puedo unzip
todos los archivos en una carpeta como esta
unzip "*".zip
Sin embargo, para eliminar todos los archivos zip posteriormente, debo hacer
rm *.zip
Es decir, no quiere las comillas. El descomprimido, por otro lado, no funciona si solo le doy el * (me advierte que "los archivos no coinciden").
¿Por qué es esto diferente? A mí me parece exactamente la misma operación. ¿O estoy usando el comodín incorrectamente?
Introducciones al comodínen Unix realmente no entra en esto, y no pude encontrar nada en los documentos rm
o zip
.
Estoy usando la terminal en una Mac (Yosemite).
Respuesta1
Has explicado muy bien la situación. La última pieza del rompecabezas es que unzip
puede manejar comodines por sí mismo:
http://www.info-zip.org/mans/unzip.html
ARGUMENTOS
archivo[.zip]
...
Las expresiones comodín son similares a las admitidas en los shells Unix de uso común (sh, ksh, csh) y pueden contener:
* coincide con una secuencia de 0 o más caracteres
Al citar el comodín *, impidió que su shell lo expandiera, por lo que unzip
ve el comodín y se ocupa de expandirlo de acuerdo con su propia lógica.
rm
, por el contrario, no admite comodinespor sí mismo, por lo que intentar citar un comodín le indicará rm
que busque un asterisco literal en el nombre del archivo.
La razón por la que unzip *.zip
no funciona es que unzip
la sintaxis de simplemente no permite múltiples archivos zip; si hay varios parámetros, espera que el segundo y los siguientes sean archivos en el archivo:
descomprimir [-Z] [-cflptTuvz[abjnoqsCDKLMUVWX$/:^]] archivo[.zip] [archivo(s) ...] [-x xarchivo(s) ...] [-d exdir]
Respuesta2
La diferencia entre esos dos comandos es el *
carácter entre comillas. Si llama a un comando en un shell y usa el *
carácter como argumento, el propio shell evaluará el argumento. Vea este ejemplo:
$ ls
file1.zip file2.zip file3.zip file4.txt
Ahora con un *
:
$ ls *.zip
file1.zip file2.zip file3.zip
El shell evalúa el comodín y genera un comando de la siguiente manera:
$ ls file1.zip file2.zip file3.zip
Con un comodín entre comillas, se interpreta como un archivo llamado (literalmente) *.zip
:
$ ls "*".zip
ls: cannot access *.zip: No such file or directory
unzip
No se puede llamar a la utilidad con varios archivos comprimidos como argumentos. Pero el desarrollador eligió otra forma de hacerlo. Desde la página de manual:
archivo[.zip]
[...] expresiones comodín son similares a las admitidas en los shells Unix de uso común (sh, ksh, csh) [...] (Asegúrese de citar cualquier carácter que de otro modo podría ser interpretado o modificado por el sistema operativo., particularmente bajo Unix y VMS.)
Respuesta3
La diferencia es que en el primer caso el propio shell expande el globo:
% cd /
% echo *
Applications Library Network System Users Volumes bin cores ...
%
mientras que en el segundo caso la propia aplicación Does Something™ con ese carácter literal:
% cd /
% perl -E 'chdir "/tmp" or die; say for glob($ARGV[0])' "*"
com.apple.launchd.aj4FEhYqm5
...
Si no está entre comillas, el shell primero expande el globo y el comando se ejecutará con cualquier cosa a la que se haya expandido ese globo del shell.
Respuesta4
Las comillas son necesarias debido a la forma en que zip maneja múltiples argumentos:
rm
: elimina todos los archivos en la lista de argumentos
zip
: descomprime el archivo en el primer argumento. solo extraiga los archivos en los argumentos restantes.
$ ls *.zip
file1.zip file2.zip file3.zip
$ unzip *.zip
Archive: file1.zip
caution: filename not matched: file2.zip
caution: filename not matched: file3.zip
Como puede ver, intenta encontrar file2.zip y file3.zip dentro de file1.zip.
Para permitirle extraer varios archivos zip a la vez, zip admite la interpretación del globo por sí mismo, con un resultado diferente.