Arquivos em lote do Windows: .bat vs .cmd?

747

Pelo que entendi, .baté a antiga convenção de nomenclatura de 16 bits e .cmdé para Windows de 32 bits, ou seja, começando com o NT. Mas continuo vendo arquivos .bat em todos os lugares e eles parecem funcionar exatamente da mesma maneira, usando um ou outro sufixo. Assumindo que meu código nunca vai precisar para rodar em qualquer coisa mais velha do que NT, isso realmente importa para que lado eu nomeio meus arquivos em lote, ou se há alguma pegadinha me aguardando usando o sufixo errado?

Chris Noe
fonte
19
Apenas para aumentar a confusão, agora também temos arquivos .ps1.
Martin Brown
42
Se não me engano, os arquivos .ps1 devem ser um arquivo do Windows Power Shell. Eu poderia estar errado.
CMS_95

Respostas:

454

Deste grupo de notícias publicado pelo próprio Mark Zbikowski :

As diferenças entre .CMD e .BAT no que diz respeito ao CMD.EXE são: Com extensões ativadas, PATH / APPEND / PROMPT / SET / ASSOC em arquivos .CMD definirá ERRORLEVEL independentemente de erro. .BAT define ERRORLEVEL apenas em erros.

Em outras palavras, se ERRORLEVEL estiver definido como diferente de 0 e você executar um desses comandos, o ERRORLEVEL resultante será:

  • deixado sozinho em seu valor diferente de 0 em um arquivo .bat
  • redefina para 0 em um arquivo .cmd.
Ben Hoffstein
fonte
4
Isso significa que o uso de um script .bat não retornaria um valor ERRORLEVEL 0 com êxito? Se isso é verdade, eu nunca notei isso.
djangofan
31
Eu acho que isso significa que, se ERRORLEVEL foi definido como diferente de 0, você executa um desses comandos, ele será deixado sozinho (diferente de 0) em um arquivo .bat, mas redefinido para 0 em um arquivo .cmd. Mas, sendo o Windows o que é, é bem possível que realmente faça com que uma voz sem corpo diga a você, no Pig Latin, "redefina você mesmo o ERRORLEVEL se você se importa tanto!".
21813 MadScientist
5
Eu acho que está dizendo que apenas esses comandos específicos fariam as ações set / not set diferentes. Outros funcionarão normalmente
PsychoData
1
Eu entendo agora. Eu atualizei minha essência. Aparentemente, ele não (re) define o nível de erro ao chamar uma set var=..instrução. O que é estranho, porque eu assumi que era um comportamento esperado. Argumentos poderiam ser feitos para ambos. Eu vou ficar com os arquivos .bat. :-)
wasatchwizard
1
Nota - O comando APPEND foi substituído pelo comando DPATH não documentado, embora DPATH /?ainda liste o comando como APPEND. Além disso, o artigo do Wiki foi corrigido principalmente, exceto que não lista o DPATH.
dbenham
417

Aqui está uma compilação de informações verificadas das várias respostas e referências citadas neste tópico:

  1. command.com é o processador de comando de 16 bits introduzido no MS-DOS e também foi usado na série de sistemas operacionais Win9x.
  2. cmd.exeé o processador de comando de 32 bits no Windows NT (os sistemas operacionais Windows de 64 bits também têm uma versão de 64 bits). cmd.exenunca fez parte do Windows 9x. Ele se originou no OS / 2 versão 1.0 e a versão do OS / 2 cmdcomeçou em 16 bits (mas ainda assim era um programa em modo protegido de pleno direito com comandos como start). Windows NT herdado cmddo OS / 2, mas a versão Win32 do Windows NT iniciou 32 bits. Embora o OS / 2 tenha 32 bits em 1992, ele cmdpermaneceu um programa OS / 2 1.x de 16 bits.
  3. A ComSpecvariável env define por qual programa é iniciado .bate .cmdscripts. (A partir do WinNT, o padrão é cmd.exe.)
  4. cmd.exeé compatível com versões anteriores command.com.
  5. Um script criado para cmd.exepode ser nomeado .cmdpara impedir a execução acidental no Windows 9x. Essa extensão de nome de arquivo também remonta ao OS / 2 versão 1.0 e 1987.

Aqui está uma lista de cmd.exerecursos que não são suportados por command.com:

  • Nomes de arquivos longos (excedendo o formato 8.3)
  • Histórico de comandos
  • Conclusão da guia
  • Caractere de escape: ^(Use para \ & | > < ^:)
  • Pilha de diretórios: PUSHD/POPD
  • Aritmética de número inteiro: SET /A i+=1
  • Pesquisar / Substituir / Substring: SET %varname:expression%
  • Substituição de comando: FOR /F(existia antes, foi aprimorada)
  • Funções: CALL :label

Ordem de Execução:

Se as versões .bat e .cmd de um script (test.bat, test.cmd) estiverem na mesma pasta e você executar o script sem a extensão (test), por padrão, a versão .bat do script será executada, mesmo no Windows 7. de 64 bits. A ordem de execução é controlada pela variável de ambiente PATHEXT. Consulte Ordem na qual o prompt de comando executa arquivos para obter mais detalhes.

Referências:

wikipedia: Comparação de shells de comando

Chris Noe
fonte
4
Vários pontos menores: 1) .bat não invoca necessariamente command.com - aparentemente quando command.com é invocado, é um mistério complexo; 2) command.com foi introduzido com o MS-DOS; 3) O cmd.exe pode executar a maioria dos scripts command.com, mas existem alguns itens menores do command.com que não funcionam no cmd.
Michael Burr
6
cmd.exe foi introduzido com o NT 4.0 acredito, não janelas 95.
FlySwat
1
Chris: veja a versão atual do artigo da Wikipedia, esp. o comentário de Mark Zbikowski em groups.google.com/group/…
Mark
2
Apenas para adicionar algumas informações sobre este assunto: dir filenameé o mesmo que dir filename.*em command.com; o curinga é necessário no cmd.exe. No command.com rem Create an empty file > empty.txtfunciona; não no cmd.exe.
Aacini 24/05
2
Apenas um pouco disso parece ser relevante para a pergunta do OP, que é sobre a diferença entre .bat e .cmd, não a diferença entre command.com e cmd.exe. Enquanto eu o li, a pergunta é sobre a diferença entre um arquivo .bat e um arquivo .cmd, todas as outras coisas sendo iguais.
Stewart
85

Essas respostas são um pouco longas e focadas no uso interativo. As diferenças importantes para scripts são:

  • .cmd impede a execução inadvertida em sistemas não-NT.
  • .cmd permite que comandos internos alterem o nível de erro para 0 em caso de êxito.

Não é tão emocionante, né?

Costumava haver vários recursos adicionais ativados nos .cmdarquivos, chamados Extensões de Comando. No entanto, agora eles estão ativados por padrão para arquivos .bate .cmdno Windows 2000 e posterior.

Conclusão: em 2012 e além, recomendo o uso .cmdexclusivo.

Gringo Suave
fonte
7
IMO, esse é o ponto principal. Você usa .cmd como extensão para scripts mais recentes quando deseja garantir que eles não sejam executados em sistemas operacionais de 16 bits mais antigos ou se não tiver certeza de que eles funcionarão.
24414 Oliver Oliver
12
Eu realmente aprecio respostas concisas, pragmáticas e claras sobre toneladas de paredes de respostas inúteis e de classe universitária.
Liquid Core
7
Sou professor universitário e concordo com o @Liquid Core! Respostas concisas, pragmáticas e claras são como aprendemos (quando ainda não sabemos algo). Então, de alguma forma, uma vez que a compreendemos, sentimos o desejo de explicá-la de maneira abstrata e incompreensível. Esquisito. Boa observação!
Eureka #
24

Não - não importa nem um pouco. No NT, as extensões .bat e .cmd fazem com que o processador cmd.exe processe o arquivo exatamente da mesma maneira.

Informações adicionais interessantes sobre command.com vs. cmd.exe nos sistemas da classe WinNT do MS TechNet ( http://technet.microsoft.com/en-us/library/cc723564.aspx ):

Esse comportamento revela um recurso bastante sutil do Windows NT que é muito importante. O shell do MS-DOS de 16 bits (COMMAND.COM) fornecido com o Windows NT foi projetado especialmente para o Windows NT. Quando um comando é inserido para execução por esse shell, ele não é realmente executado. Em vez disso, ele empacota o texto do comando e o envia para um shell de comando do CMD.EXE de 32 bits para execução. Como todos os comandos são realmente executados pelo CMD.EXE (o shell de comando do Windows NT), o shell de 16 bits herda todos os recursos e facilidades do shell completo do Windows NT.

Michael Burr
fonte
5
Isso pode importar; como o texto do link menciona, as diferenças são sutis.
Gringo Suave
Você pode forçar o command.com a executar um comando dos especificando-o na linha de comando. Veja command /c verversus iniciar command.com e digitar ver.
Phd443322
O nome importa: D Vi muitos .bat dos caras serem do passado! Use .cmd! Também não posso acreditar que NT é usado ainda hoje ...
hfrmobile
@ hfrmobile: Quando mencionei 'NT', eu quis dizer basicamente todas as versões do Windows em que estamos baseados no NT (e não no 9x). Então, basicamente, NT, Win2k e todas as versões do Windows para desktop ou servidor desde o XP. E o nome do arquivo pode fornecer informações sobre a mentalidade e o estilo de codificação da pessoa que escreveu o arquivo, mas, para o intérprete, não há diferença.
Michael Burr
16

RE: Aparentemente, quando command.com é chamado, é um mistério um pouco complexo;

Vários meses atrás, durante o curso de um projeto, tivemos que descobrir por que alguns programas que queríamos executar no CMD.EXE estavam, de fato, sendo executados no COMMAND.COM. O "programa" em questão era um arquivo .BAT muito antigo, que ainda é executado diariamente.

Descobrimos que o motivo pelo qual o arquivo em lotes foi executado no COMMAND.COM é que ele estava sendo iniciado a partir de um arquivo .PIF (também antigo). Como as configurações especiais de memória disponíveis apenas através de um PIF se tornaram irrelevantes, substituímo-lo por um atalho convencional da área de trabalho.

O mesmo arquivo em lotes, iniciado a partir do atalho, é executado no CMD.EXE. Quando você pensa sobre isso, isso faz sentido. A razão pela qual demoramos tanto tempo para descobrir isso foi parcialmente devido ao fato de termos esquecido que seu item no grupo de inicialização era um PIF, porque estava em produção desde 1998.

David Gray
fonte
1
Que sistema operacional era esse? Algo antes do XP?
Phd #
14

Ainda assim, no Windows 7, os arquivos BAT também têm essa diferença: se você criar os arquivos TEST.BAT e TEST.CMD no mesmo diretório e executar o TEST nesse diretório, ele executará o arquivo 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
fonte
Faz isso porque test.bat é alfabeticamente anterior a test.cmd. Windows faz conclusão gananciosa.
David
26
@ David: Não é verdade. Isso acontece porque na PATHEXTvariável a extensão .BAT é colocada antes do .CMD (como mostrado nesta resposta). Se você modificar essa ordem no PATHEXT, o test.cmd será executado.
Aacini 24/05
Hmm, eu esperava que eles estivessem na outra ordem; Eu acho que a MS deve ter descoberto (ou assumido) que algum software existente enviava arquivos .CMD e arquivos .BAT com o mesmo nome de base, onde os arquivos .CMD obviamente não eram destinados como entrada para o cmd (ainda não enviado). exe, mas poderia ter havido várias outras coisas: comandos para algum outro shell, um script de configuração lido pelo aplicativo ou algum tipo de aplicativo binário, por exemplo. (Pelo menos, essa é a minha compreensão da maneira usual MS acabar com aparentemente comportamento sub-óptima.)
Samb
Também é importante notar que o diretório atual vem antes de outros diretórios na PATHvariável de ambiente, independentemente da extensão.
Turkeyphant
13

Como a postagem original dizia respeito às conseqüências do uso do sufixo .bat ou .cmd , não necessariamente dos comandos dentro do arquivo ...

Outra diferença entre .bat e .cmd é que, se existirem dois arquivos com o mesmo nome e ambas as extensões, então:

  • inserir nome do arquivo ou nome do arquivo .bat na linha de comando executará o arquivo .bat

  • Para executar o arquivo .cmd, é necessário inserir o nome do arquivo .cmd

Rob na TVSeries.com
fonte
2
Eh? Se eu colocar um arquivo cmd no meu diretório, não preciso especificar a extensão do arquivo para invocá-lo. Exemplo: echo notepad.exe% *> np.cmd Então, se eu apenas digitar "np mytextfilename.txt", ele exibirá o bloco de notas. Não preciso digitar "np.cmd" para invocá-lo.
Jon Jon Davis
2
@ stimpy77: Isso é verdade se o arquivo np.cmd for o único com esse nome, mas "se existirem dois arquivos com o mesmo nome e as duas extensões" , a única maneira de executar o arquivo .cmd será a extensão. ..
Aacini 24/05
1
É uma necessidade de resolver ambiguidade para qualquer shell, nada a ver com diferenças técnicas entre .cmd vs .bat. Provavelmente é porque filename.bat precede filename.cmd em ordem alfabética.
Jon Davis
6
Na verdade, depende da PATHEXTvariável de ambiente. A ordem na qual as extensões aparecem é a ordem de precedência se uma extensão não for especificada. Também vale ressaltar que não é necessário especificar uma extensão para os arquivos cuja extensão aparece na variável env.
Ricardo Zorio 25/09
8

tudo que trabalha em um lote deve funcionar em um cmd; O cmd fornece algumas extensões para controlar o ambiente. Além disso, o cmd é executado por um novo interpretador do cmd e, portanto, deve ser mais rápido (não perceptível em arquivos curtos) e mais estável à medida que o bat é executado no ambiente de 16 bits emulado pelo NTVDM

Lorenzo Boccaccia
fonte
Não deve fazer diferença na velocidade. .batnão é executado no DOS no NT. Um VDM é iniciado apenas se um programa precisar, e nem é suportado no Windows de 64 bits, embora eu acredite que seja .bat.
Gringo Suave
3

A execução do arquivo .cmd e .bat é diferente porque em uma variável no nível de erro .cmd, ela pode ser alterada em um comando afetado pelas extensões de comando. É sobre isso mesmo.

zask
fonte
De grosso modo ^. ^ Existem diferenças na linguagem de comando usada para cada (os arquivos .bat obtêm uma versão de compatibilidade). Alguns destes pode ser ilustrado por este script a partir de aqui: @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
4
Nos arquivos .cmd, todos os comandos definem o nível de erro; nos arquivos .bat, alguns comandos deixam o nível de erro inalterado, conforme descrito na resposta aceita
jeb
1
O BAT foi criado para interagir com o COMMAND.COM, o interpretador de comandos do DOS. A Microsoft adotou a maioria dos comandos do DOS em seu novo intérprete chamado CMD. EXE. O CMD foi criado para interagir com o CMD.EXE e quebra a compatibilidade com o COMMAND.COM. principalmente conhecido por como eles lidam com a variável errorlevel. Ao usar o BAT, essa variável é alterada apenas quando ocorre um erro real e nenhuma mudança de estado ocorre quando cada comando é executado com êxito. Isso não é verdade para o CMD, pois a variável errorlevel ainda mudaria de estado, mesmo se nenhum erro ocorrer.
Zask
3

Acredito que se você alterar o valor da variável de ambiente ComSpec para %SystemRoot%system32\cmd.exe(CMD), não importa se a extensão do arquivo é .BATou .CMD. Não tenho certeza, mas isso pode até ser o padrão para o WinXP e versões posteriores.

Patrick Cuff
fonte
1

Um pouco fora do tópico, mas você já considerou o Windows Scripting Host ? Você pode achar melhor.

Marcin
fonte
13
Por falar nisso, o PowerShell, que substitui o WSH / cscript.exe.
Jon Jon Davis
3
@ stimpy77 É verdade, embora o PowerShell me pareça bastante terrível.
Marcin
2
Acho o WSH muito pior. Suponho que tudo depende do que estamos avaliando como "terrível". O PowerShell tem um tempo de inicialização atroz. Tudo sobre ele é absolutamente maravilhoso.
22912 Jon Davis
Desculpe a formatação, mas para acelerar o tempo de inicialização do PSH, tente executar: Set-Alias ​​ngen @ (dir (caminho da junção $ {env: \ windir} "Microsoft.NET \ Framework") ngen.exe -recurse | sort -descending lastwritetime) [0] .fullName [NOVA LINHA AQUI] [appdomain] :: currentdomain.getassemblies () | % {ngen $ _. location}
mjbnz 25/03
1
Completamente fora de tópico.
21919 HappyDog
1

A extensão não faz diferença.

Existem pequenas diferenças entre COMMAND.COMmanusear o arquivo vs CMD.EXE.

Waldo
fonte
-10

uma diferença:

Os arquivos .cmd são carregados na memória antes de serem executados. Os arquivos .bat executam uma linha, leem a próxima linha, executam essa linha ...

você pode se deparar com isso ao executar um arquivo de script e editá-lo antes de concluir a execução. arquivos bat ficarão bagunçados com isso, mas arquivos cmd não.

cinzento
fonte
Como foi estabelecido, a variável de ambiente ComSpec define qual programa é iniciado. Você está basicamente dizendo que command.com lê o arquivo uma linha por vez, enquanto o cmd.exe pré-carrega o arquivo na memória? Você pode citar uma referência sobre isso?
precisa
24
É errado no Vista e XP, ambos os tipos de arquivos são lidos linha por linha. Se você pausar o arquivo .cmd ou .bat e editá-lo, o novo código será executado
jeb
1
Pode-se discutir se é linha por linha, porque se você pausar a execução no meio do arquivo de comando e adicionar um caractere no início, ao reiniciar o analisador, um caractere será desativado por um caractere, possivelmente jogando fora o restante do seu script.
2
Você não deve debater .bat e .cmd não difere dessa maneira. Ambos são sempre lidos linha por linha. Você pode testá-lo se não acreditar. Crie um arquivo em lotes que o echo 1&pauseexecutará. Você verá 1e Press any key to continue.... Enquanto estiver em pausa, adicione uma nova linha echo 2&pausecom o editor externo. Pressione uma tecla Você verá 2e Press any key to continue.... Você pode até tentar adicionar echo 3&pauseno começo. Quando você pressionar uma tecla depois disso novamente, você verá 2.
venimus