Archivos por lotes de Windows: .bat vs .cmd?

747

Según tengo entendido, .bates la antigua convención de nomenclatura de 16 bits, y .cmdes para Windows de 32 bits, es decir, comenzando con NT. Pero sigo viendo archivos .bat en todas partes, y parecen funcionar exactamente igual usando cualquier sufijo. Suponiendo que nunca tendrá mi código para funcionar en cualquier cosa mayor que NT, es lo que realmente importa en qué dirección nombrar mis archivos por lotes, o hay alguna Gotcha me espera utilizando el sufijo mal?

Chris Noe
fuente
19
Solo para agregar a la confusión, ahora también tenemos archivos .ps1.
Martin Brown
42
si no me equivoco, los archivos .ps1 deberían ser un archivo Windows Power Shell. Aunque podría estar equivocado.
CMS_95

Respuestas:

454

De este grupo de noticias publicado por el propio Mark Zbikowski :

Las diferencias entre .CMD y .BAT en lo que respecta a CMD.EXE son: Con las extensiones habilitadas, PATH / APPEND / PROMPT / SET / ASSOC en archivos .CMD establecerá ERRORLEVEL independientemente del error. .BAT establece ERRORLEVEL solo en errores.

En otras palabras, si ERRORLEVEL está configurado en un valor distinto de 0 y luego ejecuta uno de esos comandos, el ERRORLEVEL resultante será:

  • dejado solo en su valor no 0 en un archivo .bat
  • restablecer a 0 en un archivo .cmd.
Ben Hoffstein
fuente
44
¿Eso implica que el uso de un script .bat no devolvería un valor ERRORLEVEL 0 en caso de éxito? Si eso es cierto, nunca lo noté.
djangofan 01 de
31
Creo que significa que si ERRORLEVEL se configuró en no 0, entonces ejecuta uno de esos comandos, se dejará solo (no 0) en un archivo .bat pero se restablecerá a 0 en un archivo .cmd. Pero, siendo Windows lo que es, es muy posible que en realidad provoque que una voz incorpórea te diga, en Pig Latin, "reinicia ERRORLEVEL tú mismo si te importa tanto".
MadScientist
55
Creo que está diciendo que solo esos comandos específicos harían las diferentes acciones set / not set. Otros funcionarán normalmente
PsychoData
1
Entiendo ahora. Actualicé mi esencia. Aparentemente, no (re) establece el nivel de error al llamar a una set var=..declaración. Lo cual es extraño, porque supuse que era un comportamiento esperado. Se podrían hacer argumentos para ambos. Me quedaré con los archivos .bat. :-)
wasatchwizard
1
Nota: el comando APPEND ha sido reemplazado por el comando DPATH no documentado, aunque DPATH /?todavía enumera el comando como APPEND. Además, el artículo de Wiki se ha corregido en su mayor parte, excepto que no incluye DPATH.
dbenham
417

Aquí hay una compilación de información verificada de las diversas respuestas y referencias citadas en este hilo:

  1. command.com es el procesador de comandos de 16 bits introducido en MS-DOS y también se utilizó en la serie Win9x de sistemas operativos.
  2. cmd.exees el procesador de comandos de 32 bits en Windows NT (los sistemas operativos Windows de 64 bits también tienen una versión de 64 bits). cmd.exenunca fue parte de Windows 9x. Se originó en OS / 2 versión 1.0, y la versión OS / 2 de cmd16 bits comenzó (pero no obstante fue un programa de modo protegido completo con comandos como start). Windows NT heredó cmdde OS / 2, pero la versión Win32 de Windows NT comenzó con 32 bits. Aunque OS / 2 pasó a 32 bits en 1992, cmdsiguió siendo un programa OS / 2 1.x de 16 bits.
  3. La ComSpecvariable env define qué programa es lanzado por .baty .cmdscripts. (Comenzando con WinNT, este valor predeterminado es cmd.exe).
  4. cmd.exees compatible con versiones anteriores command.com.
  5. Se cmd.exepuede nombrar un script diseñado para .cmdevitar la ejecución accidental en Windows 9x. Esta extensión de nombre de archivo también se remonta a OS / 2 versión 1.0 y 1987.

Aquí hay una lista de cmd.execaracterísticas que no son compatibles con command.com:

  • Nombres de archivo largos (que exceden el formato 8.3)
  • Historial de comandos
  • Pestaña completada
  • Carácter de escape: ^(Uso para: \ & | > < ^)
  • Pila de directorio: PUSHD/POPD
  • Aritmética de enteros: SET /A i+=1
  • Buscar / Reemplazar / Subcadena: SET %varname:expression%
  • Sustitución de comandos: FOR /F(existía antes, se ha mejorado)
  • Funciones: CALL :label

Orden de Ejecución:

Si las versiones .bat y .cmd de un script (test.bat, test.cmd) están en la misma carpeta y ejecuta el script sin la extensión (prueba), de forma predeterminada se ejecutará la versión .bat del script, incluso en Windows 7 de 64 bits. El orden de ejecución está controlado por la variable de entorno PATHEXT. Consulte el orden en que el símbolo del sistema ejecuta los archivos para obtener más detalles.

Referencias

wikipedia: Comparación de shells de comando

Chris Noe
fuente
44
Varios puntos menores: 1) .bat no necesariamente invoca command.com - aparentemente cuando se invoca command.com es un misterio un poco complejo; 2) command.com se introdujo con MS-DOS; 3) cmd.exe puede ejecutar la mayoría de los scripts de command.com, pero hay algunas cosas menores de command.com que no funcionan en cmd.
Michael Burr
66
cmd.exe se introdujo con NT 4.0, creo, no con Windows 95.
FlySwat
1
Chris: vea la versión actual del artículo de Wikipedia, especialmente. el comentario de Mark Zbikowski en groups.google.com/group/…
Mark
2
Solo para agregar información sobre este asunto: dir filenamees lo mismo que dir filename.*en command.com; el comodín se requiere en cmd.exe. En command.com rem Create an empty file > empty.txtfunciona; no en cmd.exe.
Aacini
2
Solo un poco de esto parece ser relevante para la pregunta del OP, que se trata de la diferencia entre .bat y .cmd, no la diferencia entre command.com y cmd.exe. Mientras lo leo, la pregunta es sobre la diferencia entre un archivo .bat y un archivo .cmd, todas las demás cosas son iguales.
Stewart
85

Estas respuestas son demasiado largas y se centran en el uso interactivo. Las diferencias importantes para las secuencias de comandos son:

  • .cmd evita la ejecución involuntaria en sistemas que no son NT.
  • .cmd permite que los comandos integrados cambien Errorlevel a 0 en caso de éxito.

No es tan emocionante, ¿eh?

Solía ​​haber una serie de características adicionales habilitadas en los .cmdarchivos, llamadas Extensiones de comando. Sin embargo, ahora están activadas por defecto para ambos .baty .cmdarchivos en Windows 2000 y versiones posteriores.

En pocas palabras: en 2012 y más allá, recomiendo usar .cmdexclusivamente.

Gringo Suave
fuente
77
OMI, ese es el punto principal. Utiliza .cmd como extensión para los scripts más nuevos cuando desea asegurarse de que no se ejecuten en sistemas operativos de 16 bits anteriores, o si no está seguro de que funcionarán.
Oliver
12
Realmente aprecio las respuestas concisas, pragmáticas y claras sobre toneladas de muros de respuestas inútiles y universitarias.
Liquid Core
77
¡Soy profesor universitario y estoy de acuerdo con @Liquid Core! Las respuestas concisas, pragmáticas y claras son cómo aprendemos (cuando todavía no sabemos algo). Entonces, de alguna manera, una vez que lo entendemos, sentimos la necesidad de explicarlo de una manera abstracta e incomprensible. Extraño. ¡Buena observación!
Eureka
24

No, no importa en lo más mínimo. En NT, las extensiones .bat y .cmd hacen que el procesador cmd.exe procese el archivo exactamente de la misma manera.

Información interesante adicional sobre command.com vs.cmd.exe en sistemas de clase WinNT de MS TechNet ( http://technet.microsoft.com/en-us/library/cc723564.aspx ):

Este comportamiento revela una característica bastante sutil de Windows NT que es muy importante. El shell de MS-DOS de 16 bits (COMMAND.COM) que se incluye con Windows NT está especialmente diseñado para Windows NT. Cuando un shell ingresa un comando para su ejecución, en realidad no lo ejecuta. En su lugar, empaqueta el texto del comando y lo envía a un shell de comando CMD.EXE de 32 bits para su ejecución. Debido a que CMD.EXE (el shell de comandos de Windows NT) ejecuta todos los comandos, el shell de 16 bits hereda todas las características e instalaciones del shell completo de Windows NT.

Michael Burr
fuente
55
Puede importar; Como su texto de enlace menciona que las diferencias son sutiles.
Gringo Suave
Puede forzar a command.com a ejecutar un comando dos al especificarlo en la línea de comando. Ver command /c verversus iniciar command.com y escribir ver.
phd443322
El nombre es importante: D ¡Vimos muchos .bat de chicos del pasado! Use .cmd! Tampoco puedo creer que NT todavía se use hoy ...
hfrmobile
@hfrmobile: Cuando mencioné 'NT' me refería básicamente a todas las versiones de Windows que estamos basadas en NT (y no 9x). Entonces, esencialmente NT, Win2k y todas las versiones de Windows para el escritorio o el servidor desde XP. Y el nombre del archivo puede dar una idea de la mentalidad y el estilo de codificación de la persona que escribió el archivo, pero para el intérprete no hay diferencia.
Michael Burr
16

RE: Aparentemente cuando se invoca command.com es un misterio un poco complejo;

Hace varios meses, durante el curso de un proyecto, tuvimos que descubrir por qué algunos programas que queríamos ejecutar bajo CMD.EXE, de hecho, se ejecutaban bajo COMMAND.COM. El "programa" en cuestión era un archivo .BAT muy antiguo, que todavía se ejecuta a diario.

Descubrimos que la razón por la que el archivo por lotes se ejecutó bajo COMMAND.COM es porque se estaba iniciando desde un archivo .PIF (también antiguo). Dado que los ajustes de configuración de memoria especiales disponibles solo a través de un PIF se han vuelto irrelevantes, lo reemplazamos con un acceso directo de escritorio convencional.

El mismo archivo por lotes, lanzado desde el acceso directo, se ejecuta en CMD.EXE. Cuando lo piensas, esto tiene sentido. La razón por la que nos tomó tanto tiempo descubrirlo se debió en parte al hecho de que habíamos olvidado que su elemento en el grupo de inicio era un PIF, porque había estado en producción desde 1998.

David Gray
fuente
1
¿Qué sistema operativo era este? Algo antes de XP?
phk
14

Aún así, en Windows 7, los archivos BAT también tienen esta diferencia: si alguna vez crea archivos TEST.BAT y TEST.CMD en el mismo directorio, y ejecuta TEST en ese directorio, ejecutará el archivo BAT.

C:\>echo %PATHEXT%
.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC

C:\Temp>echo echo bat > test.bat

C:\Temp>echo echo cmd > test.cmd

C:\Temp>test

C:\Temp>echo bat
bat

C:\Temp>
tvCa
fuente
Lo hace porque test.bat está alfabéticamente antes de test.cmd. Windows realiza una codiciosa finalización.
David
26
@David: No es cierto. Esto sucede porque en PATHEXTvariable la extensión .BAT se coloca antes de .CMD one (como se muestra en esta respuesta). Si modifica este orden en PATHEXT, el test.cmd se ejecutará en su lugar.
Aacini
Hmm, esperaba que estuvieran en el otro orden; Supongo que MS debe haber descubierto (o asumido) que algún software existente incluía archivos .CMD y archivos .BAT con el mismo nombre base, donde los archivos .CMD, por supuesto, no estaban destinados como entrada para el cmd (aún no enviado). exe, pero podría haber muchas otras cosas: comandos para algún otro shell, un script de configuración leído por la aplicación, o algún tipo de binario de la aplicación, por ejemplo. (Al menos, esa es mi comprensión de la forma habitual en que la EM termina con un comportamiento aparentemente subóptimo.)
SamB
También vale la pena señalar que el directorio actual está antes que otros directorios en la PATHvariable de entorno, independientemente de la extensión.
Turkeyphant
13

Dado que la publicación original se refería a las consecuencias del uso del sufijo .bat o .cmd , no necesariamente los comandos dentro del archivo ...

Otra diferencia entre .bat y .cmd es que si existen dos archivos con el mismo nombre de archivo y ambas extensiones, entonces:

  • ingresar el nombre del archivo o el nombre del archivo .bat en la línea de comando ejecutará el archivo .bat

  • para ejecutar el archivo .cmd, debe ingresar el nombre de archivo .cmd

Rob en TVSeries.com
fuente
2
Eh? Si pongo un archivo cmd en mi directorio, no tengo que especificar la extensión del archivo para invocarlo. Ejemplo: echo notepad.exe% *> np.cmd Luego, si solo escribo "np mytextfilename.txt", aparecerá el bloc de notas. No tengo que escribir "np.cmd" para invocarlo.
Jon Davis
2
@ stimpy77: Esto es cierto si np.cmd es el único archivo con ese nombre, pero "si existen dos archivos con el mismo nombre y ambas extensiones" , entonces la única forma de ejecutar el .cmd es incluir su extensión. ..
Aacini
1
Esta es una necesidad de resolver la ambigüedad de cualquier shell, nada que ver con las diferencias técnicas entre .cmd vs .bat. Probablemente sea porque filename.bat precede a filename.cmd alfabéticamente.
Jon Davis
66
De hecho, depende de la PATHEXTvariable de entorno. El orden en que aparecen las extensiones es el orden de precedencia si no se especifica una extensión. También vale la pena mencionar que no es necesario especificar una extensión para los archivos cuya extensión aparece en la variable env.
Ricardo Zorio
8

todo lo que funciona en un lote debería funcionar en un cmd; cmd proporciona algunas extensiones para controlar el entorno. Además, cmd se ejecuta en un nuevo intérprete de cmd y, por lo tanto, debería ser más rápido (no se nota en archivos cortos) y más estable a medida que bat se ejecuta en el entorno de 16 bits emulado NTVDM

Lorenzo Boccaccia
fuente
No debería hacer ninguna diferencia en la velocidad. .batno se ejecuta bajo DOS en NT. Un VDM solo se inicia si un programa lo necesita, y ni siquiera es compatible con Windows de 64 bits, aunque creo que .bat sí.
Gringo Suave
3

La ejecución de archivos .cmd y .bat es diferente porque en una variable de nivel de error .cmd puede cambiar en un comando que se ve afectado por las extensiones de comando. Eso es todo realmente.

zask
fuente
De grueso ^. ^ Hay diferencias en el lenguaje de comando utilizado para cada uno (los archivos .bat obtienen una versión de compatibilidad). Algunos de éstos pueden ilustrarse con este script desde aquí: @echo off&setlocal ENABLEEXTENSIONS call :func&&echo/I'm a cmd||echo/I'm a bat goto :EOF :func md;2>nul set var=1
Zask
44
En los archivos .cmd cada comando establece el nivel de error, en los archivos .bat algunos comandos dejan el nivel de error sin cambios, como se describe en la respuesta aceptada
jeb
1
BAT fue creado para interactuar con COMMAND.COM, el intérprete de comandos de DOS. Microsoft adoptó la mayoría de los comandos de DOS en su nuevo intérprete llamado CMD. EXE. CMD fue creado para interactuar con CMD.EXE y rompe la compatibilidad con COMMAND.COM. principalmente conocido por cómo manejan la variable de nivel de error. Cuando se usa BAT, esta variable solo se cambia una vez que se produce un error real y no se produce ningún cambio en el estado cuando cada comando se ejecuta con éxito. Esto no es cierto para CMD ya que la variable de nivel de error aún cambiaría de estado incluso si no se producen errores.
zask
3

Creo que si cambia el valor de la variable de entorno ComSpec a %SystemRoot%system32\cmd.exe(CMD), no importa si la extensión del archivo es .BATo .CMD. No estoy seguro, pero esto incluso puede ser el predeterminado para WinXP y superior.

Patrick Cuff
fuente
1

Ligeramente fuera de tema, pero ¿ha considerado Windows Scripting Host ? Puede que te resulte más agradable.

Marcin
fuente
13
Para el caso, PowerShell, que desprecia WSH / cscript.exe.
Jon Davis
3
@ stimpy77 Cierto, aunque powershell me parece bastante terrible.
Marcin
2
Encuentro WSH mucho peor. Supongo que todo depende de lo que estemos midiendo como "terrible". PowerShell tiene un tiempo de inicio atroz. Todo al respecto es absolutamente maravilloso OMI.
Jon Davis
Disculpe el formato, pero para acelerar el tiempo de inicio de PSH, intente ejecutar: Set-Alias ​​ngen @ (dir (join-path $ {env: \ windir} "Microsoft.NET \ Framework") ngen.exe -recurse | sort -descending lastwritetime) [0] .fullName [NUEVA LÍNEA AQUÍ] [appdomain] :: currentdomain.getassemblies () | % {ngen $ _. location}
mjbnz
1
Completamente fuera de tema.
HappyDog
1

La extensión no hace ninguna diferencia.

Existen ligeras diferencias entre COMMAND.COMel manejo del archivo vs CMD.EXE.

Waldo
fuente
-10

una diferencia:

Los archivos .cmd se cargan en la memoria antes de ejecutarse. Los archivos .bat ejecutan una línea, leen la siguiente línea, ejecutan esa línea ...

puede encontrar esto cuando ejecuta un archivo de script y luego lo edita antes de que termine de ejecutarse. Esto dañará los archivos bat, pero los archivos cmd no.

gris
fuente
Como se ha establecido, la variable env de ComSpec define qué programa se inicia, ¿está diciendo esencialmente que command.com lee el archivo línea por línea, mientras que cmd.exe precarga el archivo en la memoria? ¿Puedes citar una referencia sobre esto?
Chris Noe
24
Está mal para Vista y XP, ambos tipos de archivos se leen línea por línea. Si pausa el archivo .cmd o .bat y lo edita, el nuevo código se ejecutará
jeb
1
Uno podría debatir si es línea por línea, porque si pausa la ejecución en el medio del archivo de comando y agrega un carácter al principio, al reanudar el analizador se desactivará un carácter, posiblemente eliminando el resto de su script.
2
No debe debatir .bat y .cmd no difiere de esa manera. Ambos siempre se leen línea por línea. Puedes probarlo si no crees. Haga un archivo por lotes que echo 1&pauseluego lo ejecute. Verás 1y Press any key to continue.... Mientras está en pausa, agregue una nueva línea echo 2&pausecon un editor externo. Presione una tecla. Verás 2y Press any key to continue.... Incluso puede intentar agregar echo 3&pauseal principio. Cuando presione una tecla después de eso nuevamente verá 2.
venimus