CMD: *. * O solo *?

47

En la década de 1990, usaría " *.*" para representar cualquier nombre de archivo en MS-DOS, pero he visto más scripts usando solo " *" estos días. ¿Realmente hace alguna diferencia cuál uso?

Foebane
fuente
99
Si bien es cierto que *y *.*ahora son equivalentes a cmdlos comandos internos y modernas utilidades de línea de comandos, algunas utilidades de más edad que tienen parámetros de máscara de archivo pueden utilizar las funciones de comparación de archivos de más edad, y para ellos las máscaras no serán equivalentes.
AFH
@AFH No creo que las fichas sean iguales. El *.*token no debería devolver archivos sin extensión.
tuskiomi
1
@tuskiomi: estoy de acuerdo con usted en que *.* no debería devolver archivos sin extensión. Lamentablemente lo hace. Ver la respuesta de Grawity.
AFH

Respuestas:

65

El nombre y la extensión del archivo han sido un solo campo desde que Windows 95 y NT 3.5 introdujeron la compatibilidad con "nombre de archivo largo", y las coincidencias con comodines se realizan contra todo el nombre de archivo a la vez. Como resultado, puede tener un nombre de archivo sin puntos (tal vez raro para archivos, pero muy común para carpetas / directorios) y, a primera vista *.*, en realidad no coincidiría con dichos archivos.

El uso de scripts antiguos *.* seguirá funcionando debido al código de compatibilidad: si el comodín termina con .*, el sistema operativo ignora esa parte . (Por lo tanto, si desea hacer coincidir específicamente los archivos con una extensión, supongo que necesitaría *.?*eso).

Pero no es algo en lo que deba confiar; Si está escribiendo scripts para versiones modernas de Windows, siga sus convenciones, no las convenciones de MS-DOS. (Tenga en cuenta que a partir de Windows NT, los scripts .bat ya no son interpretados por MS-DOS sino por cmd.exeun programa Win32 nativo).


En Linux y varios otros Unixen, el nombre y la extensión nunca se han separado en primer lugar, y no hay ninguna magia especial para hacer el *.*trabajo, por lo que *es la única opción que tiene sentido.

Gravedad
fuente
14
"¡Hagamos que sea más difícil filtrar archivos con extensiones! ¡Yay!" -Desarrollador anónimo de Microsoft
John Hamilton
50
"¡Rompamos los millones de scripts de lotes existentes para todos! ¡Yay!" -No Microsoft Developer, Ever
grawity
3
ISTR que en algunas versiones antiguas de DOS, *solo coincidiría con nombres de archivos sin una extensión. La forma "segura" de ser compatible con ambos era usar **.
Random832
8
El OP se trata de Windows, pero como ha mencionado Linux: en algunos shells (Bash, por ejemplo), *( por defecto ) no coincide con los nombres de archivos ocultos (comenzando con a .).
Florian Brucker
44
Para algunos valores de "nivel de sistema operativo" ... También es realmente un concepto de shell (Explorer) en Windows: al núcleo no le importa .exe en los ejecutables, ni nada más. Se puede discutir si Windows Explorer tiene más "nivel de sistema operativo" que, por ejemplo, Nautilus en Linux.
Grawity
11

Probablemente vale la pena mencionar que el unixy / conchas posixy como bourne shell, bash, ksh, zsh, etc. hacen expansión de comodines (de caracteres glob como *, ?, [range], [!range]y otras expansiones como llaves y globos largos) para compilar una lista de argumentos antes de la orden es ejecutado. Entonces, esta expansión la realiza el shell, no el comando para el cual estos pueden ser argumentos.

es decir, el shell es responsable de qué *, se *.*expande a

 $ ls
 file.csv  file.doc  file.pdf  file.txt  file.xlsx  zz-file-without-extension

 $ (set -xv; foo *)   # is actually expanded to the following
   + foo file.csv file.doc file.pdf file.txt file.xlsx zz-file-without-extension

 $ (set -xv; foo *.*)  # note this does not match `zz-file-without-extension`
   + foo file.csv file.doc file.pdf file.txt file.xlsx

Este no es el caso en CMD (y de manera similar para las utilidades de PowerShell ) ya que pasa los caracteres glob textualmente al comando ejecutado, por lo que la expansión es responsabilidad del comando / utilidad y no del shell. Entonces, en última instancia, qué *.*o qué *medios le queda a la utilidad dejándola conforme (o no) a las convenciones, razón por la cual las utilidades de CMD dir *.*también coinciden (posiblemente incorrectamente pero conservando las expectativas) archivos sin extensiones.

Creo que es seguro resumir de esta manera.

  • Bajo CMD depende de la utilidad.
  • Bajo PowerShell, las utilidades que hacen uso de la clase WildCardPattern proporcionarán un subconjunto consistente de comportamientos posixy.
shalomb
fuente
Otra diferencia es que bajo CMD, la mayoría de los programas en realidad reenvían el comodín sin procesar al kernel (FindFirstFile), mientras que glob en Linux solo toma la lista completa y filtra en el espacio de usuario.
Grawity
Cuando ejecuta * en un directorio con un millón de archivos, el comando se quejará de demasiados parámetros. En el peor de los casos, podría caer silenciosamente la cola de la lista. En esos casos, necesita canalizar dos o más comandos, o guardar una lista de nombres de archivo en un archivo, para que otro proceso pueda leer la lista.
Enric Naval
3
@grawity Para ser más precisos, el filtrado se realiza mediante el controlador del sistema de archivos en Windows. Esto es especialmente útil en los sistemas de archivos de red (especialmente cuando se podía ejecutar una línea de 8 kb a un sistema de archivos remoto), pero también significa que no puede realizar búsquedas arbitrarias ni búsquedas explícitamente compatibles. Las implicaciones de esto se han explorado muchas veces en el blog de Raymond Chen. FindFirstFileen sí mismo es en modo de usuario (tanto kernel32.dll como ntdll.dll son bibliotecas en modo de usuario; es parte del subsistema Win32, no el núcleo), pero en realidad no hace mucho.
Luaan
Ah, tenía la impresión de que FindFirstFile envolvía casi directamente un syscall de nombre similar (como qué tan abierto (3) en libc simplemente envuelve abierto (2) en el kernel de Linux).
Grawity
1
@cup: solo use comillas para evitar que el shell expanda los globos, para que pueda pasarlos a los comandos. por ej mmv "fred.*" "tom.#1". (El reemplazo usa en #1lugar de *, lo que tiene la ventaja de permitirle reordenar los campos). mmvno está instalado de manera predeterminada en la mayoría de los sistemas, pero a menudo otras herramientas de cambio de nombre de lotes sí lo están. Vea este artículo al respecto y stackoverflow.com/questions/417916/how-to-do-a-mass-rename .
Peter Cordes