Windows批处理文件:.bat与.cmd?


747

据我了解,它.bat是旧的16位命名约定,.cmd适用于32位Windows,即以NT开头。但是我仍然到处都能看到.bat文件,无论使用哪个后缀,它们看起来都可以完全相同地工作。假设我的代码永远不需要在NT之前的任何版本上运行,那么我以哪种方式命名批处理文件真的很重要,还是因为使用了错误的后缀而使我有些困惑


19
只是为了增加混乱,我们现在还有.ps1文件。
马丁·布朗

42
如果我没有记错的话,.ps1文件应该是Windows Power Shell文件。我可能是错的。
CMS_95

Answers:


454

马克·兹比科夫斯基本人发表新闻组中

就CMD.EXE而言,.CMD和.BAT之间的区别是:启用扩展名后,.CMD文件中的PATH / APPEND / PROMPT / SET / ASSOC将设置ERRORLEVEL而不考虑错误。.BAT仅对错误设置ERRORLEVEL。

换句话说,如果将ERRORLEVEL设置为非0,然后运行这些命令之一,则产生的ERRORLEVEL将为:

  • 在.bat文件中单独保留其非零值
  • 在.cmd文件中重置为0。

4
这是否意味着使用.bat脚本成功不会返回ERRORLEVEL 0值?如果那是真的,我从没注意到。
djangofan 2013年

31
我认为这意味着如果ERRORLEVEL设置为非0,则您运行这些命令之一,它将在.bat文件中单独保留(非0),但在.cmd文件中重置为0。但是,Windows是它的本质,它很有可能实际上引起了具体化的声音,用Pig Latin告诉您:“如果您这么在意,请重设错误级别!”。
MadScientist 2013年

5
我认为这是只有那些特定的命令才能执行不同的设置/不设置操作。其他人将像往常一样工作
PsychoData

1
我现在知道了。我更新了要点。显然,它在调用set var=..语句时不会(重新)设置错误级别。这很奇怪,因为我认为这是预期的行为。两者都可以争论。我会坚持使用.bat文件。:-)
wasatchwizard

1
注-尽管APPEND命令DPATH /?仍被列为APPEND ,但已被未记录的DPATH命令替换。此外,此后Wiki文章已得到更正,但未列出DPATH。
dbenham '16

417

以下是该线程中各种答案和引用参考中经过验证的信息的汇总:

  1. command.com 是MS-DOS中引入的16位命令处理器,也用于Win9x系列操作系统中。
  2. cmd.exe是Windows NT中的32位命令处理器(64位Windows操作系统也有64位版本)。cmd.exe从来都不是Windows 9x的一部分。它起源于OS / 2版本1.0,并且OS / 2版本cmd开始于16位(但是仍然是带有命令的成熟的保护模式程序start)。Windows NT cmd从OS / 2 继承而来,但是Windows NT的Win32版本从32位开始。尽管OS / 2在1992年成为32位,但它cmd仍然是16位OS / 2 1.x程序。
  3. ComSpec环境变量定义哪些程序由发射.bat.cmd脚本。(从WinNT开始,默认为cmd.exe。)
  4. cmd.exe向后兼容command.com
  5. cmd.exe可以命名一个专门设计的脚本,.cmd以防止在Windows 9x上意外执行。此文件扩展名也可以追溯到OS / 2版本1.0和1987。

以下是cmd.exe不支持的功能的列表command.com

  • 长文件名(超过8.3格式)
  • 命令历史
  • 制表符补全
  • 转义字符:^(适用于:\ & | > < ^
  • 目录堆栈:PUSHD/POPD
  • 整数运算: SET /A i+=1
  • 搜索/替换/子字符串: SET %varname:expression%
  • 命令替换:(FOR /F以前存在,已得到增强)
  • 功能: CALL :label

执行顺序:

如果脚本的.bat和.cmd版本(test.bat,test.cmd)都位于同一文件夹中,并且您运行的脚本没有扩展名(测试),则默认情况下,脚本的.bat版本将运行,即使在64位Windows 7上。执行的顺序由PATHEXT环境变量控制。有关更多详细信息,请参见命令提示符执行文件的顺序

参考文献:

维基百科:命令外壳的比较


4
有几点要点:1).bat不一定会调用command.com-显然,在调用command.com时有点复杂。2)在MS-DOS中引入了command.com;3)cmd.exe可以运行大多数command.com脚本,但是有一些次要的command.com东西在cmd中不起作用。
Michael Burr

6
CMD.EXE与NT 4.0中引入的,我相信,而不是Windows 95
FlySwat

1
克里斯:请参阅Wikipedia文章的当前版本,尤其是。马克Zbikowski在groups.google.com/group/…上
马克

2
只是添加一些有关此问题的信息:dir filenamedir filename.*command.com中的相同;cmd.exe中需要通配符。在command.com中rem Create an empty file > empty.txt工作;不在cmd.exe中。
阿萨尼(Aacini)2015年

2
似乎只有一点点与OP的问题有关,该问题与.bat和.cmd之间的差异有关,而与command.com和cmd.exe之间的差异无关。在我阅读本文时,问题是关于.bat文件和.cmd文件之间的区别,其他所有条件都相同。
斯图尔特

85

这些答案太长了,只能用于交互式使用。脚本编制的重要区别是:

  • .cmd 防止在非NT系统上无意执行。
  • .cmd 使内置命令在成功时将Errorlevel更改为0。

不是那么令人兴奋,是吗?

文件中曾经有许多启用的附加功能.cmd,称为命令扩展。但是,现在默认情况下,Windows 2000和更高版本下的.bat.cmd文件都启用了它们。

底线:在2012年及以后,我建议.cmd仅使用。


7
海事组织,这是重点。如果要确保在较旧的16位OS上不执行这些脚本,请使用.cmd作为新脚本的扩展名,或者不确定它们是否可以运行。
奥利弗

12
我真的很感谢简洁,务实和清晰的答案,这些答案就像是无用的,大学类的答案一样。
液芯

7
我是大学教授,我同意@Liquid Core!简洁,务实,清晰的答案是我们学习的方式(当我们尚不了解时)。然后,以某种方式,一旦我们理解了它,便感到有一种以抽象和难以理解的方式来解释它的冲动。奇怪的。好观察!
尤里卡

24

不-一点也没有关系。在NT上,.bat和.cmd扩展名都使cmd.exe处理器以完全相同的方式处理文件。

MS TechNet(http://technet.microsoft.com/zh-cn/library/cc723564.aspx)上有关WinNT类系统上的command.com与cmd.exe的其他有趣信息:

此行为表明Windows NT的非常微妙的功能非常重要。Windows NT附带的16位MS-DOS外壳程序(COMMAND.COM)是专门为Windows NT设计的。当此外壳输入要执行的命令时,它实际上不会执行。而是,它将命令文本打包并将其发送到32位CMD.EXE命令外壳以执行。因为所有命令实际上都是由CMD.EXE(Windows NT命令外壳程序)执行的,所以16位外壳程序继承了完整Windows NT外壳程序的所有功能。


5
这可能很重要;正如您的链接文字所提到的,差异是细微的。
Gringo Suave

您可以通过在命令行上指定command.com来强制执行dos命令。请参阅command /c ver与启动command.com并键入ver。
phd443322

名称很重要:D看到很多来自家伙的.bat都是过去的!使用.cmd!也不能相信今天仍在使用NT ...
hfrmobile 2015年

@hfrmobile:当我提到“ NT”时,我指的是基本上所有基于NT的Windows版本(而不是9x)。从XP开始,从本质上讲,NT,Win2k以及台式机或服务器的所有Windows版本都可以使用。文件的名称可以使您深入了解编写文件的人的思维方式和编码风格,但就解释器而言,没有什么区别。
Michael Burr 2015年

16

RE:显然,当调用command.com时,这有点复杂。

几个月前,在项目过程中,我们不得不弄清楚为什么我们要在CMD.EXE下运行的某些程序实际上在COMMAND.COM下运行。有问题的“程序”是一个非常老的.BAT文件,仍然每天运行。

我们发现批处理文件在COMMAND.COM下运行的原因是它是从.PIF文件启动的(也是古老的)。由于仅通过PIF可用的特殊内存配置设置已变得无关紧要,因此我们将其替换为常规的桌面快捷方式。

从快捷方式启动的同一批处理文件在CMD.EXE中运行。当您考虑时,这很有意义。我们花了这么长时间才弄清楚这个问题的部分原因是因为我们已经忘记了它在启动组中的项目是PIF,因为它从1998年开始生产。


1
这是什么操作系统?XP之前的东西?
phk

14

不过,在Windows 7上,BAT文件也有此区别:如果您曾经在同一目录中创建文件TEST.BAT和TEST.CMD,并且在该目录中运行TEST,它将运行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>

这样做是因为test.bat按字母顺序在test.cmd之前。Windows确实贪婪完成。
戴维(David)

26
@大卫:不是真的。发生这种情况是因为在PATHEXT变量.BAT扩展名放在.CMD之前(如此答案所示)。如果您在PATHEXT中修改此顺序,则将改为执行test.cmd。
阿萨尼(Aacini)

嗯,我希望他们能排在另一个顺序。我猜想MS一定已经发现(或假设)某些现有软件附带了具有相同基本名称的.CMD文件和.BAT文件,这些.CMD文件当然不打算用作(尚未发货)cmd的输入。 exe,但可能还有许多其他事情:例如其他外壳程序的命令,应用程序读取的配置脚本或某种应用程序二进制文件。(至少,这是我对MS最终出现看似次优行为的通常方式的理解。)
SamB

还值得注意的是,当前目录在PATH环境变量中位于其他目录之前,而不管扩展名如何。
Turkeyphant

13

由于原来的文章是关于使用.bat或.cmd的后果后缀,不一定是命令里面的文件...

.bat和.cmd之间的另一个区别是,如果存在两个具有相同文件名和两个扩展名的文件,则:

  • 在命令行中输入文件名文件名 .bat将运行.bat文件

  • 要运行.cmd文件,必须输入文件名 .cmd


2
??如果我将cmd文件放在目录中,则无需指定文件扩展名即可调用它。示例:echo notepad.exe%*> np.cmd然后,如果我只是键入“ np mytextfilename.txt”,它将弹出记事本。我不必键入“ np.cmd”来调用它。
乔恩·戴维斯

2
@ stimpy77:如果np.cmd是唯一一个具有该名称的文件,则为true,但“如果存在两个具有相同文件名和两个扩展名的文件”,则执行.cmd的唯一方法就是包括其扩展名。 ..
阿萨尼(Aacini)2015年

1
解决任何外壳的歧义都是必要的,与.cmd和.bat之间的技术差异无关。这可能是因为filename.bat按字母顺序在filename.cmd之前。
乔恩·戴维斯

6
它实际上取决于PATHEXT环境变量。如果未指定扩展名,则出现扩展名的顺序是优先顺序。还值得一提的是,不必为扩展名显示在env变量中的文件指定扩展名。
里卡多·佐里奥

8

批量工作的所有内容都应在cmd中工作;cmd提供了一些用于控制环境的扩展。另外,cmd由新的cmd解释器执行,因此应该更快(在短文件中不可见),并且由于bat在NTVDM模拟的16位环境下运行,因此更稳定


速度不应有任何差异。 .bat不能在NT中的DOS下运行。VDM仅在程序需要时才启动,甚至在64位Windows中也不支持,尽管我相信.bat是。
Gringo Suave

3

.cmd和.bat文件的执行不同,因为在.cmd错误级别变量中,它可以在受命令扩展名影响的命令上更改。就是这样。


粗略的^。^每种命令的语言有所不同(.bat文件获得兼容版本)。这些脚本中的一些可以从下面的脚本中得到说明: @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
在.cmd文件中,每个命令都设置错误级别,在.bat文件中,某些命令将错误级别保持不变,如公认的答案所述
jeb 2016年

1
创建BAT是为了与DOS的命令解释器COMMAND.COM进行交互。Microsoft将大多数DOS命令采用到了名为CMD的新解释器中。可执行程序。创建CMD是为了与CMD.EXE接口,它破坏了与COMMAND.COM的兼容性。主要因为它们如何处理errorlevel变量而闻名。使用BAT时,仅在发生实际错误时才更改此变量,并且在成功执行每个命令时不会更改状态。对于CMD,情况并非如此,因为即使没有错误发生,错误级别变量仍会更改状态。
zask '16

3

我相信,如果将ComSpec环境变量的值更改为%SystemRoot%system32\cmd.exe(CMD),则文件扩展名是.BAT还是都没有关系.CMD。我不确定,但这甚至可能是WinXP及更高版本的默认设置。


1

话题不大,但是您是否考虑过Windows Scripting Host?您可能会觉得更好。


13
为此,PowerShell不赞成WSH / cscript.exe。
乔恩·戴维斯

3
@ stimpy77是的,尽管powershell对我来说似乎很糟糕。
Marcin 2012年

2
我发现WSH更糟。我想这一切都取决于我们对“可怕”的衡量。PowerShell的启动时间非常糟糕。有关它的一切绝对是很棒的IMO。
乔恩·戴维斯

请原谅格式,但要加快PSH启动时间,请尝试运行:Set-Alias ngen @(dir(join-path $ {env:\ windir}“ Microsoft.NET \ Framework”)ngen.exe -recurse | sort -descending lastwritetime)[0] .fullName [NEW LINE HERE] [appdomain] :: currentdomain.getassemblies()| %{ngen $
_。location

1
完全偏离主题。
HappyDog

1

该扩展没有区别。

COMMAND.COM处理档案与档案之间有细微差异CMD.EXE


-10

区别:

.cmd文件在执行之前已加载到内存中。.bat文件执行一行,读取下一行,然后执行该行...

您可以在执行脚本文件时遇到此问题,然后在执行完毕之前对其进行编辑。bat文件将因此而混乱,但cmd文件不会。


正如已经确定的那样,ComSpec env变量定义了启动哪个程序,您实际上是在说command.com一次读取一行文件,而cmd.exe将文件预加载到内存中吗?您可以在此引用参考吗?
克里斯·诺

24
Vista和XP是错误的,两种文件类型都是逐行读取的。如果您暂停.cmd或.bat文件并对其进行编辑,则将执行新代码
jeb 2010年


1
可能会逐行争论,因为如果您在命令文件的中间暂停执行并在开头添加一个字符,则在恢复分析器时,解析器将被一个字符隔开,可能会抛出脚本的其余部分。

2
您不应争论.bat和.cmd不会以这种方式有所不同。两者总是一行一行地读取。如果您不相信,可以进行测试。制作一个批处理文件,echo 1&pause然后执行它。您将看到1Press any key to continue...。暂停时,echo 2&pause使用外部编辑器添加新行。按一个键。您将看到2Press any key to continue...。您甚至可以尝试echo 3&pause在开始时添加。当您再次按下某个键时,您将看到2
venimus 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.