File batch di Windows: .bat vs .cmd?


747

A quanto ho capito, .batè la vecchia convenzione di denominazione a 16 bit ed .cmdè per Windows a 32 bit, ovvero a partire da NT. Ma continuo a vedere file .bat ovunque e sembrano funzionare esattamente allo stesso modo usando entrambi i suffissi. Supponendo che il mio codice non dovrà mai essere eseguito su qualcosa di più vecchio di NT, è davvero importante il modo in cui assegno i miei file batch o c'è qualche codice che mi sta aspettando usando il suffisso sbagliato?


19
Solo per aggiungere alla confusione ora abbiamo anche file .ps1.
Martin Brown

42
se non sbaglio i file .ps1 dovrebbero essere un file Power Shell di Windows. Potrei sbagliarmi però.
CMS_95,

Risposte:


454

Da questo gruppo di notizie pubblicato dallo stesso Mark Zbikowski :

Le differenze tra .CMD e .BAT per quanto riguarda CMD.EXE sono: Con le estensioni abilitate, PATH / APPEND / PROMPT / SET / ASSOC nei file .CMD imposteranno ERRORLEVEL indipendentemente dall'errore. .BAT imposta ERRORLEVEL solo su errori.

In altre parole, se ERRORLEVEL è impostato su un valore diverso da 0 e quindi si esegue uno di questi comandi, ERRORLEVEL risultante sarà:

  • lasciato solo al suo valore diverso da 0 in un file .bat
  • reimpostato su 0 in un file .cmd.

4
Ciò implica che l'utilizzo di uno script .bat non restituirebbe un valore ERRORLEVEL 0 in caso di successo? Se questo è vero, non l'ho mai notato.
Djangofan,

31
Penso che significhi che se ERRORLEVEL fosse impostato su un valore diverso da 0, quindi esegui uno di questi comandi, verrà lasciato solo (diverso da 0) in un file .bat ma reimpostato su 0 in un file .cmd. Ma, dato che Windows è quello che è, è del tutto possibile che in realtà una voce disincarnata ti dica, in latino latino, "resetta ERRORLEVEL se ti interessa così tanto!".
MadScientist,

5
Penso che stia dicendo che solo quei comandi specifici farebbero le diverse azioni set / non set. Altri funzioneranno normalmente
PsychoData,

1
Ora capisco. Ho aggiornato il mio succo. Apparentemente, non (re) imposta il livello di errore quando si chiama set var=..un'istruzione. Il che è strano, perché ho pensato che fosse un comportamento previsto. Argomenti potrebbero essere fatti per entrambi. Continuerò con i file .bat. :-)
wasatchwizard,

1
Nota: il comando APPEND è stato sostituito con il comando DPATH non documentato, sebbene DPATH /?il comando sia ancora elencato come APPEND. Inoltre, l'articolo Wiki è stato per lo più corretto, tranne che non elenca DPATH.
dbenham,

417

Ecco una raccolta di informazioni verificate dalle varie risposte e riferimenti citati in questo thread:

  1. command.com è il processore di comando a 16 bit introdotto in MS-DOS ed è stato utilizzato anche nella serie di sistemi operativi Win9x.
  2. cmd.exeè il processore di comandi a 32 bit in Windows NT (i sistemi operativi Windows a 64 bit hanno anche una versione a 64 bit). cmd.exenon ha mai fatto parte di Windows 9x. È nato in OS / 2 versione 1.0 e la versione OS / 2 di ha cmdiniziato a 16 bit (ma era comunque un programma in modalità protetta a tutti gli effetti con comandi simili start). Windows NT ereditato cmdda OS / 2, ma la versione Win32 di Windows NT è stata avviata a 32 bit. Sebbene OS / 2 sia andato a 32 bit nel 1992, è cmdrimasto un programma OS / 2 1.x a 16 bit.
  3. La ComSpecvariabile env definisce quale programma è lanciato da .bate .cmdscript. (A partire da WinNT, l'impostazione predefinita è cmd.exe.)
  4. cmd.exeè retrocompatibile con command.com.
  5. Uno script progettato per cmd.exepuò essere nominato .cmdper impedire l'esecuzione accidentale su Windows 9x. Questa estensione di file risale anche alla versione 1.0 e 1987 di OS / 2.

Ecco un elenco di cmd.exefunzionalità che non sono supportate da command.com:

  • Nomi di file lunghi (superando il formato 8.3)
  • Cronologia dei comandi
  • Completamento della scheda
  • Carattere di escape: ^(utilizzare per \ & | > < ^:)
  • Stack di directory: PUSHD/POPD
  • Aritmetica intera: SET /A i+=1
  • Ricerca / sostituzione / Substring: SET %varname:expression%
  • Sostituzione comando: FOR /F(esisteva prima, è stato migliorato)
  • funzioni: CALL :label

Ordine di esecuzione:

Se entrambe le versioni .bat e .cmd di uno script (test.bat, test.cmd) si trovano nella stessa cartella e si esegue lo script senza l'estensione (test), per impostazione predefinita verrà eseguita anche la versione .bat dello script, anche su Windows a 64 bit 7. L'ordine di esecuzione è controllato dalla variabile d'ambiente PATHEXT. Vedere Ordine in cui il prompt dei comandi esegue i file per ulteriori dettagli.

Riferimenti:

wikipedia: confronto delle shell dei comandi


4
Diversi punti minori: 1) .bat non invoca necessariamente command.com - apparentemente quando viene chiamato command.com è un po 'un mistero complesso; 2) command.com è stato introdotto con MS-DOS; 3) cmd.exe può eseguire la maggior parte degli script command.com, ma ci sono alcune cose minori di command.com che non funzionano in cmd.
Michael Burr,

6
Credo che cmd.exe sia stato introdotto con NT 4.0, non con Windows 95.
FlySwat,

1
Chris: vedi la versione corrente dell'articolo di Wikipedia, esp. il commento di Mark Zbikowski su groups.google.com/group/…
Mark

2
Solo per aggiungere alcune informazioni su questo argomento: dir filenameè lo stesso dir filename.*di command.com; il jolly è richiesto in cmd.exe. In command.com rem Create an empty file > empty.txtfunziona; non in cmd.exe.
Aacini,

2
Solo un po 'di questo sembra essere rilevante per la domanda del PO, che riguarda la differenza tra .bat e .cmd, non la differenza tra command.com e cmd.exe. Mentre lo leggo, la domanda riguarda la differenza tra un file .bat e un file .cmd, a parità di altre condizioni.
Stewart,

85

Queste risposte sono un po 'troppo lunghe e focalizzate sull'uso interattivo. Le differenze importanti per lo scripting sono:

  • .cmd impedisce l'esecuzione involontaria su sistemi non NT.
  • .cmd abilita i comandi integrati a modificare Errorlevel a 0 in caso di successo.

Non è così eccitante, eh?

C'erano un certo numero di funzionalità aggiuntive abilitate nei .cmdfile, chiamate estensioni di comando. Tuttavia, ora sono attivati per impostazione predefinita per entrambi .bate .cmdfile in Windows 2000 e versioni successive.

In conclusione: nel 2012 e oltre, consiglio di utilizzare .cmdesclusivamente.


7
IMO, questo è il punto principale. Si utilizza .cmd come estensione per gli script più recenti quando si desidera assicurarsi che non vengano eseguiti su sistemi operativi a 16 bit precedenti o se non si è sicuri che funzioneranno.
Oliver,

12
Apprezzo molto le risposte concise, pragmatiche e chiare su tonnellate di muri di risposte inutili, simili a classi universitarie.
Liquid Core,

7
Sono professore universitario e sono d'accordo con @Liquid Core! Risposte concise, pragmatiche, chiare sono il modo in cui impariamo (quando non sappiamo ancora qualcosa). Quindi, in qualche modo, una volta capito, sentiamo il bisogno di spiegarlo in modo astratto e incomprensibile. Strano. Buona osservazione!
Eureka,

24

No, non importa minimamente. Su NT l'estensione .bat e .cmd fanno sì che il processore cmd.exe elabori il file esattamente allo stesso modo.

Ulteriori informazioni interessanti su command.com vs. cmd.exe su sistemi di classe WinNT da MS TechNet ( http://technet.microsoft.com/en-us/library/cc723564.aspx ):

Questo comportamento rivela una caratteristica abbastanza sottile di Windows NT che è molto importante. La shell MS-DOS a 16 bit (COMMAND.COM) fornita con Windows NT è appositamente progettata per Windows NT. Quando un comando viene immesso per l'esecuzione da questa shell, in realtà non lo esegue. Comprime invece il testo del comando e lo invia a una shell dei comandi CMD.EXE a 32 bit per l'esecuzione. Poiché tutti i comandi vengono effettivamente eseguiti da CMD.EXE (la shell dei comandi di Windows NT), la shell a 16 bit eredita tutte le funzionalità e le funzionalità della shell completa di Windows NT.


5
Potrebbe importare; come il testo del tuo link menziona le differenze sono sottili.
Gringo Suave,

È possibile forzare command.com per eseguire un comando dos specificandolo sulla riga di comando. Vedere command /c veranziché avviare command.com e digitare ver.
phd443322,

Il nome conta: D Ho visto molti .bat da ragazzi del passato! Usa .cmd! Inoltre non posso credere che NT sia ancora usato oggi ...
hfrmobile

@hfrmobile: quando ho citato "NT" intendevo praticamente tutte le versioni di Windows basate su NT (e non su 9x). Quindi essenzialmente NT, Win2k e tutte le versioni di Windows per desktop o server da XP. E il nome del file può dare un'idea della mentalità e dello stile di codifica della persona che ha scritto il file, ma per quanto riguarda l'interprete non c'è differenza.
Michael Burr,

16

RE: Apparentemente quando viene chiamato command.com è un po 'un mistero complesso;

Diversi mesi fa, nel corso di un progetto, abbiamo dovuto capire perché alcuni programmi che volevamo eseguire sotto CMD.EXE, in effetti, erano in esecuzione su COMMAND.COM. Il "programma" in questione era un file .BAT molto vecchio, che viene ancora eseguito quotidianamente.

Abbiamo scoperto che il motivo per cui il file batch è stato eseguito in COMMAND.COM è che veniva avviato da un file .PIF (anche antico). Poiché le speciali impostazioni di configurazione della memoria disponibili solo tramite un PIF sono diventate irrilevanti, l'abbiamo sostituito con un collegamento desktop convenzionale.

Lo stesso file batch, avviato dal collegamento, viene eseguito in CMD.EXE. Quando ci pensi, questo ha senso. Il motivo per cui ci è voluto così tanto tempo per capirlo era parzialmente dovuto al fatto che avevamo dimenticato che il suo articolo nel gruppo di avvio era un PIF, perché era in produzione dal 1998.


1
Che sistema operativo era questo? Qualcosa prima di XP?
phk,

14

Tuttavia, su Windows 7, i file BAT hanno anche questa differenza: se si creano file TEST.BAT e TEST.CMD nella stessa directory e si esegue TEST in quella directory, verrà eseguito il file 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>

Lo fa perché test.bat è in ordine alfabetico prima di test.cmd. Windows fa un avido completamento.
David,

26
@ David: non vero. Ciò accade perché nella PATHEXTvariabile l'estensione .BAT è posizionata prima di quella .CMD (come mostrato in questa risposta). Se modifichi questo ordine in PATHEXT, verrebbe eseguito invece test.cmd.
Aacini,

Speravo che fossero nell'altro ordine; Immagino che MS abbia scoperto (o ipotizzato) che alcuni software esistenti spedivano file .CMD e file .BAT con lo stesso nome di base, dove i file .CMD non erano ovviamente intesi come input per il cmd (non ancora spedito). exe, ma avrebbe potuto essere un numero qualsiasi di altre cose: comandi per qualche altra shell, uno script di configurazione letto dall'applicazione, o una sorta di binario dell'applicazione, per esempio. (Almeno, questa è la mia comprensione del solito modo in cui la SM finisce con un comportamento apparentemente non ottimale.)
SamB

Vale anche la pena notare che la directory corrente precede altre directory nella PATHvariabile d'ambiente indipendentemente dall'estensione.
Turkeyphant,

13

Poiché il post originale riguardava le conseguenze dell'uso del suffisso .bat o .cmd , non necessariamente i comandi all'interno del file ...

Un'altra differenza tra .bat e .cmd è che se esistono due file con lo stesso nome ed entrambe le estensioni, allora:

  • inserendo il nome file o il nome file .bat dalla riga di comando verrà eseguito il file .bat

  • per eseguire il file .cmd, devi inserire il nome file .cmd


2
Eh? Se inserisco un file cmd nella mia directory non devo specificare l'estensione del file per invocarlo. Esempio: echo notepad.exe% *> np.cmd Quindi, se digito "np mytextfilename.txt", verrà visualizzato Notepad. Non devo digitare "np.cmd" per invocarlo.
Jon Davis,

2
@ stimpy77: questo è vero se np.cmd è l'unico file con quel nome, ma "se esistono due file con lo stesso nome ed entrambe le estensioni" , l'unico modo per eseguire quello .cmd è includerne l'estensione. ..
Aacini,

1
Questa è una necessità di risolvere l'ambiguità per qualsiasi shell, nulla a che fare con le differenze tecniche tra .cmd vs .bat. Probabilmente è perché il nomefile.bat precede il nomefile.cmd in ordine alfabetico.
Jon Davis,

6
In realtà dipende dalla PATHEXTvariabile d'ambiente. L'ordine in cui vengono visualizzate le estensioni è l'ordine di precedenza se non viene specificata un'estensione. Vale anche la pena ricordare che non è necessario specificare un'estensione per i file che appare nella variabile env.
Ricardo Zorio,

8

tutto ciò che lavora in un batch dovrebbe funzionare in un cmd; cmd fornisce alcune estensioni per il controllo dell'ambiente. inoltre, cmd viene eseguito da un nuovo interprete cmd e quindi dovrebbe essere più veloce (non evidente su file brevi) e più stabile quando bat funziona nell'ambiente a 16 bit emulato NTVDM


Non dovrebbe fare alcuna differenza nella velocità. .batnon funziona sotto DOS in NT. Un VDM viene avviato solo se un programma ne ha bisogno e non è nemmeno supportato in Windows a 64 bit, anche se credo che lo sia .bat.
Gringo Suave,

3

L'esecuzione dei file .cmd e .bat è diversa perché in una variabile di livello di errore .cmd può cambiare in un comando interessato dalle estensioni di comando. Questo è tutto.


Di massima ^. ^ Esistono differenze nel linguaggio di comando utilizzato per ciascuno (i file .bat ottengono una versione di compatibilità). Alcuni di questi possono essere illustrati da questo script da qui: @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
Nei file .cmd ogni comando imposta il livello di errore, nei file .bat alcuni comandi lasciano invariato il livello di errore, come descritto nella risposta accettata
jeb

1
BAT è stato creato per interagire con COMMAND.COM, l'interprete dei comandi di DOS. Microsoft ha adottato la maggior parte dei comandi DOS nel nuovo interprete chiamato CMD. EXE. CMD è stato creato per interfacciarsi con CMD.EXE e interrompe la compatibilità con COMMAND.COM. principalmente noto per come gestiscono la variabile errorlevel. Quando si utilizza la BAT, questa variabile viene modificata solo quando si verifica un errore effettivo e non si verifica alcun cambiamento di stato quando ciascun comando viene eseguito correttamente. Questo non è vero per CMD poiché la variabile del livello di errore cambierebbe ancora stato anche se non si verificano errori.
Zask

3

Credo che se cambi il valore della variabile d'ambiente ComSpec in %SystemRoot%system32\cmd.exe(CMD), non importa se l'estensione del file è .BATo .CMD. Non ne sono sicuro, ma potrebbe anche essere il valore predefinito per WinXP e versioni successive.


1

Leggermente fuori tema, ma hai considerato Windows Scripting Host ? Potresti trovarlo più bello.


13
Del resto, PowerShell, che deprecava WSH / cscript.exe.
Jon Davis,

3
@ stimpy77 Vero, anche se PowerShell mi sembra piuttosto terribile.
Marcin,

2
Trovo WSH molto peggio. Suppongo che tutto dipenda da ciò che stiamo misurando per "terribile". PowerShell ha tempi di avvio atroci. Tutto ciò è assolutamente meraviglioso IMO.
Jon Davis,

Scusa la formattazione, ma per accelerare il tempo di avvio di PSH, prova a eseguire: Set-Alias ​​ngen @ (dir (join-path $ {env: \ windir} "Microsoft.NET \ Framework") ngen.exe -recurse | sort -descending lastwritetime) [0] .fullName [NUOVA LINEA QUI] [appdomain] :: currentdomain.getassemblies () | % {ngen $ _. location}
mjbnz

1
Completamente fuori tema.
Happy Dog

1

L'estensione non fa differenza.

Vi sono lievi differenze tra la COMMAND.COMgestione del file e CMD.EXE.


-10

una differenza:

I file .cmd vengono caricati in memoria prima di essere eseguiti. I file .bat eseguono una riga, leggono la riga successiva, eseguono quella riga ...

puoi trovarlo quando esegui un file di script e poi lo modifichi prima che sia terminata l'esecuzione. i file bat saranno confusi da questo, ma i file cmd no.


Com'è stato stabilito, la variabile env ComSpec definisce quale programma viene avviato, in sostanza stai dicendo che command.com legge il file una riga alla volta, mentre cmd.exe precarica il file in memoria? Puoi citare un riferimento su questo?
Chris Noe,

24
È errato per Vista e XP, entrambi i tipi di file vengono letti riga per riga. Se metti in pausa il file .cmd o .bat e lo modifichi, il nuovo codice verrà eseguito
jeb


1
Si potrebbe discutere se si tratta di riga per riga, perché se si interrompe l'esecuzione nel mezzo del file di comando e si aggiunge un carattere all'inizio, al momento della ripresa il parser verrà disattivato da un carattere, eventualmente eliminando il resto della sceneggiatura.

2
Non dovresti discutere .bat e .cmd non differiscono in questo modo. Entrambi sono sempre letti riga per riga. Puoi provarlo se non ci credi. Crea un file batch che lo abbia echo 1&pausequindi eseguito. Vedrai 1e Press any key to continue.... Mentre in pausa aggiungi una nuova riga echo 2&pausecon editor esterno. Premi un tasto. Vedrai 2e Press any key to continue.... Puoi anche provare ad aggiungere echo 3&pauseall'inizio. Quando premi di nuovo un tasto, vedrai 2.
venimus,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.