据我所知,.bat是旧的16位命名约定,.cmd用于32位窗口,即从NT开始。但是我仍然可以在任何地方看到.bat文件,它们使用任何一个后缀的工作方式似乎都完全相同。假设我的代码永远不需要在NT之前的任何东西上运行,那么我命名批处理文件的方式是否真的很重要,或者是否有人用错误的后缀等待我?
- 只是为了增加混乱,我们现在也有.ps1文件。
- 如果我没有弄错的话.ps1文件应该是Windows Power Shell文件。但我可能错了。
- @你是对的。
从Mark Zbikowski自己发布的这个新闻组:
The differences between .CMD and .BAT as far as CMD.EXE is concerned
are: With extensions enabled, PATH/APPEND/PROMPT/SET/ASSOC in .CMD
files will set ERRORLEVEL regardless of error. .BAT sets ERRORLEVEL
only on errors.
换句话说,如果将ErrorLevel设置为非0,然后运行这些命令之一,则生成的ErrorLevel将为:
- 在.bat文件中保持其非0值
- 在.cmd文件中重置为0。
- 这是否意味着使用.bat脚本不会在成功时返回错误级别0值?如果这是真的,我从来没有注意到。
- 我认为这意味着如果错误级别被设置为非0,那么您运行这些命令之一,它将在.bat文件中单独存在(非0),但在.cmd文件中重置为0。但是,Windows是这样的,它很可能会让一个无实体的声音用猪拉丁语告诉你,"如果你这么在乎的话,自己重置错误等级!".
- 我认为只有那些特定的命令才能执行不同的设置/不设置操作。其他人会像正常人一样工作
- 我不同意设置错误级别。但是,也许我不明白你们的意思。我总是从批处理文件返回正确的错误级别!如果我执行一个返回负错误级别的命令,如dir c:\doesntexist,那么执行一个返回成功的命令,如dir"%temp%—错误级别设置正确。请参阅:gist.github.com/kodybrown/7430acd13634c682ae75。我刚在Windows10上测试过这个,但是我在7/8/8.1中做过这个,我很确定它也可以在XP上工作。(不知道它是否适用于Vista!反正是谁用的!?)
- 我现在明白了。我更新了我的要点。显然,在调用set var=..语句时,它不会(重新)设置错误级别。这很奇怪,因为我假设这是预期的行为。这两个问题都可以争论。我会继续使用.bat文件。-)
- 注意-append命令已替换为未记录的dpath命令,尽管DPATH /?仍然将该命令列为append。此外,维基的文章大部分都被修改了,只是没有列出dpath。
- ftype命令也只在由.cmd脚本执行时将errorlevel清除为0。
- 我不知道有什么行为上的区别;我认为唯一的区别是,.cmd文件被发送到command.com而不是cmd.exe的可能性更小,因为DOS可能不会搜索它们(默认情况下),Windows 9x也不会与它们关联。带回家是你可以证明跳过任何"这是cmd.exe吗?"在.cmd中检查,但不在.bat中检查。(32位Windows仍然具有DOS兼容性,对吗?)
- 什么使它有意义?
以下是本主题中各种答案和引用的参考资料的核实信息汇编:
command.com是MS-DOS中引入的16位命令处理器,也用于Win9X系列操作系统。
cmd.exe是WindowsNT中的32位命令处理器(64位WindowsOSE也有64位版本)。cmd.exe从来不是Windows9x的一部分。它起源于OS/2版本1.0,而cmd的OS/2版本开始于16位(不过,它是一个完全成熟的保护模式程序,具有像start这样的命令)。WindowsNT从OS/2继承了cmd,但WindowsNT的win32版本是从32位开始的。虽然OS/2在1992年变成了32位,但它的cmd仍然是一个16位的OS/2 1.x程序。
ComSpecenv变量定义由.bat和.cmd脚本启动的程序。(从winnt开始,默认为cmd.exe。)
cmd.exe与command.com向后兼容。
为cmd.exe设计的脚本可以命名为.cmd,以防止在Windows 9x上意外执行。此文件扩展名也可以追溯到OS/2版本1.0和1987。
以下是command.com不支持的cmd.exe功能列表:
- 长文件名(超过8.3格式)
- 命令历史
- 制表完成
- 转义符:^(用于:\ & | > < ^)
- 目录栈:PUSHD/POPD。
- 整数算术:SET /A i+=1。
- 搜索/替换/子字符串:SET %varname:expression%。
- 命令替换:FOR /F(以前存在,已经增强)
- 功能:CALL :label。
执行令:
如果脚本的.bat和.cmd版本(test.bat,test.cmd)都在同一文件夹中,并且在不使用扩展名(test)的情况下运行脚本,则默认情况下,脚本的.bat版本将运行,即使在64位Windows 7上也是如此。执行顺序由pathext环境变量控制。有关详细信息,请参见命令提示执行文件的顺序。
参考文献:
维基百科:命令shell的比较
- 几个要点:1).bat不一定调用command.com-显然,当command.com被调用时有点复杂;2)command.com是用ms-dos引入的;3)cmd.exe可以运行大多数command.com脚本,但有一些小command.com在cmd中不起作用。
- 嘿,迈克,如果你对command.com的一些不适用于cmd.exe的特性有任何具体的了解,我想应该在上面单独给出一个答案。
- 我在win9x或do s上工作已经很久了,我唯一能记住的就是你可以做一些类似"cd…"的事情来提升多个目录级别(嘿,我说的是次要的,不是吗?)不过,有关command.com在NT上的处理信息,请参阅我编辑的答案。
- Cmd.exe是由NT 4.0引入的,我相信不是Windows 95。
- 克里斯:看看维基百科文章的最新版本,特别是马克·兹比科夫斯基在groups.google.com/group/&hellip上的评论;
- 使用command.com,您可以加载ansi.sys来为文本着色启用ansi转义代码。我不确定是否可以在cmd.exe中加载ansi.sys。
- @糖蜜:你不能。不过,对于64位系统来说,现在这是一个没有意义的问题。
- 1987年,OS/2 1.0版引入了第cmd号和新的.cmd公约,作为专门针对cmd而非command的命令脚本文件的扩展。
- 别名和历史记录是控制台窗口(conhost.exe或csrss.exe)的函数,而不是cmd.exe。历史记录与F7弹出框集成。每个附加的程序都有自己的历史和别名,由控制台API或通过doskey从命令行进行管理。
- @Michaelburr也许您指的是使用命令CD ..\..\..在目录结构中向上导航(将向上移动3级)?
- 只是增加一些关于这件事的信息:dir filename与command.com中的dir filename.*相同;在cmd.exe中需要通配符。在command.com中,rem Create an empty file > empty.txt有效;不在cmd.exe中。
- @aacini,关于创建空文件:rem也可以在cmd中工作,但只能这样:rem/>empty.txt(而不是/可以很好地使用以下字符:. \ : + [ ];注意( )不工作);
- 最佳答案。我想指出我选择.cmd而不是.bat的主要现实原因是为了故意阻止脚本在16位上运行,但这种情况越来越少见。
- 其中只有一点似乎与op的问题有关,即.bat和.cmd之间的区别,而不是command.com和cmd.exe之间的区别。当我读到它时,问题是关于.bat文件和.cmd文件之间的区别,所有其他的东西都是相等的。
这些答案有点太长,主要集中在交互使用上。脚本编写的重要区别在于:
- .cmd防止在非NT系统上意外执行。
- .cmd允许内置命令在成功时将错误级别更改为0。
默认情况下,在Windows 2000或更高版本下的.bat和.cmd文件中,命令扩展名都处于打开状态。
2012年及以后,我建议只使用.cmd。
- 在我看来,这是重点。如果您想确保新脚本不会在旧的16位OSS上执行,或者如果您不确定它们是否可以工作,可以使用.cmd作为新脚本的扩展名。
- 我真的很欣赏简洁、务实和清晰的答案,这些答案覆盖了无数无用的、像大学课堂一样的答案。
不-一点关系都没有。在NT上,.bat和.cmd扩展名都会使cmd.exe处理器以完全相同的方式处理文件。
有关ms-technet中Winnt类系统上command.com与cmd.exe的其他有趣信息(http://technet.microsoft.com/en-us/library/cc723564.aspx):
This behavior reveals a quite subtle
feature of Windows NT that is very
important. The 16-bit MS-DOS shell
(COMMAND.COM) that ships with Windows
NT is specially designed for Windows
NT. When a command is entered for
execution by this shell, it does not
actually execute it. Instead, it
packages the command text and sends it
to a 32-bit CMD.EXE command shell for
execution. Because all commands are
actually executed by CMD.EXE (the
Windows NT command shell), the 16-bit
shell inherits all the features and
facilities of the full Windows NT
shell.
- 这可能很重要;正如您的链接文本所提到的,差异是微妙的。
- 您可以通过在命令行上指定命令来强制command.com执行DOS命令。参见command /c ver与starting command.com,并键入ver。
- 名字很重要:我见过很多。男人的球棒都是过去的!使用,CMD!也不敢相信NT现在还在使用…
- @hfrmobile:当我提到"nt"时,我的意思是基本上所有基于nt(而不是9x)的Windows版本。因此,本质上是NT、Win2K以及自XP以来桌面或服务器的所有Windows版本。文件名可以让人了解写文件的人的思维方式和编码风格,但就口译员而言,没有什么不同。
回复:显然,当command.com被调用是一个复杂的谜;
几个月前,在一个项目的过程中,我们必须弄清楚为什么我们想要在cmd.exe下运行的一些程序实际上是在command.com下运行的。所讨论的"程序"是一个非常旧的.bat文件,仍然每天运行。
我们发现批处理文件在command.com下运行的原因是它是从一个.pif文件(也很古老)启动的。由于只有通过PIF才可用的特殊内存配置设置变得不相关,因此我们将其替换为传统的桌面快捷方式。
从快捷方式启动的同一批文件在cmd.exe中运行。当你想到它时,这是有道理的。我们花了这么长时间才弄明白这一点的部分原因是,我们忘记了它在创业集团中的项目是一个PIF,因为它自1998年开始生产。
由于最初的文章是关于使用.bat或.cmd后缀的结果,所以不一定是文件中的命令…
.bat和.cmd的另一个区别是,如果存在两个具有相同文件名和两个扩展名的文件,那么:
- 嗯?如果我在目录中放置了一个cmd文件,就不需要指定文件扩展名来调用它。示例:echo notepad.exe%*>np.cmd,然后如果我只键入"np mytextfilename.txt",它将显示记事本。我不需要输入"np.cmd"来调用它。
- @stimpy77:如果np.cmd是唯一具有该名称的文件,但"如果存在两个具有相同文件名和两个扩展名的文件",则执行.cmd的唯一方法是包含其扩展名…
- 这是解决任何shell的歧义的必要性,与.cmd与.bat之间的技术差异无关。这可能是因为filename.bat按字母顺序在filename.cmd之前。
- 它实际上取决于PATHEXT环境变量。如果未指定扩展名,则扩展名的显示顺序为优先顺序。值得一提的是,不必为扩展名出现在env变量中的文件指定扩展名。
不过,在Windows7上,BAT文件也有这样的区别:如果在同一目录中创建了test.bat和test.cmd文件,并且在该目录中运行了test,那么它将运行BAT文件。
1 2 3 4 5 6 7 8 9 10 11 12 13
| 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完成得很贪婪。
- @大卫:不是真的。这是因为在PATHEXT变量中,.bat扩展名放在.cmd one之前(如此答案所示)。如果在pathext中修改此顺序,则会改为执行test.cmd。
- 嗯,我希望它们是按另一个顺序排列的;我想微软一定发现(或假定)一些现有的软件已经发送了.cmd文件和.bat文件,它们具有相同的基名,其中.cmd文件当然不打算作为(尚未发送)cmd.exe的输入,但也可能是其他许多东西:用于其他shell的命令应用程序读取的配置脚本或某种应用程序二进制文件。(至少,这是我对MS以看似次优行为结束的通常方式的理解。)
在批处理中工作的所有内容都应该在命令中工作;命令提供了一些用于控制环境的扩展。另外,命令由新的命令解释器执行,因此在NTVDM模拟的16位环境下,当BAT运行时,命令应该更快(在短文件中不明显)并且更稳定。
- 速度不应该有什么不同。在NT中,.bat不在DOS下运行。vdm只有在程序需要时才启动,64位窗口甚至不支持它,尽管我相信.bat是。
.cmd和.bat文件的执行是不同的,因为在.cmd errorlevel变量中,它可以更改受命令扩展名影响的命令。这是真的。
- 你能出示样品吗
- 粗略的^.^每个(.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
- 在.cmd文件中,每个命令都设置错误级别,.bat文件中,一些命令保持错误级别不变,如接受的答案中所述。
- 粗糙的井。
- BAT是为与DOS的命令解释器command.com交互而创建的。微软将大多数DOS命令应用到他们新的名为cmd的解释器中。EXE。创建cmd是为了与cmd.exe接口,它破坏了与command.com的兼容性。主要是知道他们如何处理错误级别变量。使用BAT时,只有在发生实际错误时才会更改此变量,并且在成功执行每个命令时不会更改状态。这对cmd来说不是真的,因为即使没有错误发生,errorlevel变量仍然会改变状态。
稍微偏离主题,但您考虑过Windows脚本宿主吗?你可能会发现它更好。
- 为此,PowerShell拒绝使用wsh/cscript.exe。
- @Stimpy77是真的,虽然PowerShell对我来说很糟糕。
- 我觉得WSH更糟。我想这一切都取决于我们对"可怕"的衡量。PowerShell启动时间太长。在我看来,一切都非常美好。
- 请原谅格式化,但要加快PSH启动时间,请尝试运行:set alias ngen@(dir(join path$env:windir"microsoft.netframework")ngen.exe-recurse sort-Descending lastwritetime)[0].fullname[此处为新行][appdomain]::currentdomain.getassembles()%ngen$location
我相信如果您将comspec环境变量的值更改为%systemroot%system32cmd.exe,那么文件扩展名是.bat还是.cmd并不重要。我不确定,但这可能是WinXP及更高版本的默认设置。
扩展没有区别。command.com处理文件与cmd.exe之间存在细微的差异
我发现了一个区别:EnableDelayedExpansion在.cmd文件中是必需的。如果与.bat文件一样,默认情况下是隐式的。(Windows 10)
1 2 3 4 5
| dir *? | find /i"FOOBAR"
if ERRORLEVEL 0 (
set result="found" ) else (
set result="not found" )
echo %result% |
这在.bat中有效,但在.cmd文件中始终是found。将line 2更改为以下内容使其按预期工作:
最后,对于.cmd文件,这是正确的:
1 2 3 4
| setLocal EnableDelayedExpansion
...
if !ErrorLevel! equ 1 (
... |
- 由于IF ERRORLEVEL 0对于任何0级或以上的错误都是正确的,所以它应该总是跳转到found路径。使用Windows7与您的示例没有任何区别
- @ujjwalsing Microsoft支持文章测试批处理文件中的特定错误级别详细解释了if errorlevel X,它的工作方式从MS-DOS到Windows 10,独立于具有文件扩展名bat或cmd的批处理文件。if errorlevel X语法根本不需要延迟扩展。MS-DOS、Windows 3.x、Windows 95和Windows 98不支持延迟扩展,但即使是那些古老的操作系统也支持if errorlevel X。
差异:
.cmd文件在执行前已加载到内存中。.bat文件执行一行,读取下一行,执行该行…
您可以在执行脚本文件时遇到这种情况,然后在执行完成之前对其进行编辑。BAT文件会被这个弄得一团糟,但是命令文件不会。
- 正如已经建立的那样,comspec env变量定义了启动哪个程序,您基本上是说command.com一次读取一行文件,而cmd.exe将文件预加载到内存中吗?你能举出这方面的参考资料吗?
- Vista和XP都是错误的,两种文件类型都是逐行读取的。如果暂停.cmd或.bat文件并对其进行编辑,则将执行新代码。
- 您可能会想到jp软件的替换命令解释程序所使用的.btm("批到内存")文件。
- 有人可能会争论它是否是逐行执行的,因为如果在命令文件的中间暂停执行并在开始时添加一个字符,那么在恢复解析器时,解析器将被一个字符关闭,可能会丢弃脚本的其余部分。
- 你不应该辩论.bat和.cmd在这方面没有区别。两者都是逐行阅读的。如果你不相信,你可以测试它。生成一个拥有echo 1&pause的批处理文件,然后执行它。你会看到1和Press any key to continue...。暂停时,用外部编辑器添加一行新的echo 2&pause。按一个键。你会看到2和Press any key to continue...。您甚至可以尝试在开始时添加echo 3&pause。当你再按一次键后,你会看到2。
- 我认为grey把.cmd文件和.com文件混淆了,它们被加载到内存中,但在任何意义上都不是批处理文件。