Пакетные файлы Windows: .bat против .cmd?

747

Насколько я понимаю, .batэто старое 16-битное соглашение об именах, и оно .cmdпредназначено для 32-битной Windows, то есть начиная с NT. Но я продолжаю видеть файлы .bat везде, и они, кажется, работают точно так же, используя любой суффикс. Предполагая, что мой код никогда не должен будет выполняться на чем-то более старом, чем NT, действительно ли имеет значение, каким образом я называю свои командные файлы, или есть какие-то ошибки, ожидающие меня с использованием неправильного суффикса?

Крис Но
источник
19
Просто чтобы добавить к путанице, теперь у нас также есть файлы .ps1.
Мартин Браун
42
если я не ошибаюсь .ps1 файлы должны быть Windows Power Shell. Хотя я могу ошибаться.
CMS_95

Ответы:

454

Из этой группы новостей проводки по Mark Zbikowski сам:

Различия между .CMD и .BAT в том, что касается CMD.EXE, заключаются в следующем: при включенных расширениях PATH / APPEND / PROMPT / SET / ASSOC в файлах .CMD устанавливает ERRORLEVEL независимо от ошибки. .BAT устанавливает ERRORLEVEL только при ошибках.

Другими словами, если для ERRORLEVEL установлено значение, отличное от 0, а затем вы запустите одну из этих команд, в результате ERRORLEVEL будет:

  • оставить в покое, отличном от 0 в файле .bat
  • сбросить до 0 в файле .cmd.
Бен Хоффштейн
источник
4
Означает ли это, что использование сценария .bat не вернет значение ERRORLEVEL 0 в случае успеха? Если это правда, я никогда этого не замечал.
Джангофан
31
Я думаю, это означает, что если ERRORLEVEL был установлен не в 0, то вы запустите одну из этих команд, она останется одна (не 0) в файле .bat, но сбросится в 0 в файле .cmd. Но, поскольку Windows является тем, чем она является, вполне возможно, что на самом деле это заставляет беззвучный голос сказать вам в Pig Latin: «Сбросьте ERRORLEVEL самостоятельно, если вам так важно!».
Безумный ученый
5
Я думаю, это говорит о том, что только эти конкретные команды будут выполнять различные действия set / not set. Другие будут работать как обычно
PsychoData
1
Теперь я понимаю. Я обновил мою суть. По-видимому, он не (повторно) устанавливает уровень ошибки при вызове set var=..оператора. Что странно, потому что я предположил, что это было ожидаемое поведение. Аргументы могут быть сделаны для обоих. Я буду придерживаться .bat файлов. :-)
wasatchwizard
1
Примечание. Команда APPEND была заменена недокументированной командой DPATH, хотя она по- DPATH /?прежнему перечисляется как APPEND. Кроме того, статья Wiki с тех пор была в основном исправлена, за исключением того, что в ней нет DPATH.
dbenham
417

Вот подборка проверенной информации из различных ответов и цитируемых ссылок в этой теме:

  1. command.com 16-разрядный командный процессор, представленный в MS-DOS и использовавшийся в операционных системах серии Win9x.
  2. cmd.exe32-разрядный командный процессор в Windows NT (64-разрядные ОС Windows также имеют 64-разрядную версию). cmd.exeникогда не был частью Windows 9x. Он появился в OS / 2 версии 1.0, а версия OS / 2 cmdстала 16-разрядной (но, тем не менее, была полноценной программой защищенного режима с такими командами start). Windows NT унаследована cmdот OS / 2, но версия Win32 для Windows NT начала работать с 32-разрядной версией. Хотя OS / 2 стала 32-битной в 1992 году, она cmdосталась 16-битной программой OS / 2 1.x.
  3. ComSpecПеременная ENV определяет , какая программа запускается .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) находятся в одной и той же папке, и вы запускаете скрипт без расширения (test), по умолчанию будет запущена версия скрипта .bat, даже на 64-битной Windows 7. Порядок выполнения контролируется переменной среды PATHEXT. См. Порядок, в котором командная строка выполняет файлы для получения дополнительной информации.

Ссылки:

Википедия: Сравнение командных оболочек

Chris Noe
источник
4
Несколько незначительных моментов: 1) .bat не обязательно вызывает command.com - очевидно, когда command.com вызывается, это немного сложная загадка; 2) command.com был представлен с MS-DOS; 3) cmd.exe может запускать большинство сценариев command.com, но есть несколько незначительных вещей command.com, которые не работают в cmd.
Майкл Берр
6
cmd.exe был представлен с NT 4.0, я полагаю, не с Windows 95.
FlySwat
1
Крис: см. Текущую версию статьи в Википедии, особенно комментарий Марка Збиковского на groups.google.com/group/…
Марк
2
Просто добавить некоторую информацию по этому вопросу: так dir filenameже, как dir filename.*в command.com; подстановочный знак требуется в cmd.exe. В command.com rem Create an empty file > empty.txtработает; не в cmd.exe.
Аачини
2
Похоже, лишь малая часть этого относится к вопросу OP, касающемуся разницы между .bat и .cmd, а не разницы между command.com и cmd.exe. Когда я это читаю, вопрос касается разницы между файлом .bat и файлом .cmd, при прочих равных условиях.
Стюарт
85

Эти ответы слишком длинные и ориентированы на интерактивное использование. Важные отличия для сценариев:

  • .cmd предотвращает непреднамеренное выполнение в системах, отличных от NT.
  • .cmd позволяет встроенным командам изменить уровень ошибки на 0 в случае успеха.

Не так интересно, а?

Раньше в .cmdфайлах был включен ряд дополнительных функций , называемых расширениями команд. Однако теперь они включены по умолчанию как для файлов, так .batи .cmdдля Windows 2000 и более поздних версий.

Итог: в 2012 году и далее я рекомендую использовать .cmdисключительно.

Гринго Суаве
источник
7
ИМО, это главное. Вы используете .cmd в качестве расширения для новых сценариев, когда хотите убедиться, что они не выполняются в старых 16-разрядных ОС, или если вы не уверены, что они будут работать.
Оливер
12
Я действительно ценю краткие, прагматичные и ясные ответы за тоннами стен бесполезных, похожих на университетский класс ответов.
Жидкое ядро
7
Я профессор университета, и я согласен с @Liquid Core! Краткие, прагматичные, четкие ответы - это то, как мы учимся (когда мы еще ничего не знаем). Затем, так или иначе, как только мы понимаем это, мы чувствуем потребность объяснить это абстрактно и непостижимо. Weird. Хорошее наблюдение!
Эврика
24

Нет - это не имеет значения ни в малейшей степени. В NT расширение .bat и .cmd приводят к тому, что процессор cmd.exe обрабатывает файл одинаково.

Дополнительная интересная информация о command.com против cmd.exe в системах класса WinNT от MS TechNet ( http://technet.microsoft.com/en-us/library/cc723564.aspx ):

Такое поведение раскрывает довольно тонкую особенность Windows NT, которая очень важна. 16-разрядная оболочка MS-DOS (COMMAND.COM), которая поставляется с Windows NT, специально разработана для Windows NT. Когда команда вводится для выполнения этой оболочкой, она фактически не выполняет ее. Вместо этого он упаковывает текст команды и отправляет его в 32-разрядную командную оболочку CMD.EXE для выполнения. Поскольку все команды фактически выполняются CMD.EXE (командная оболочка Windows NT), 16-разрядная оболочка наследует все функции и возможности полной оболочки Windows NT.

Майкл Берр
источник
5
Это может иметь значение; как упоминается в тексте вашей ссылки, различия незначительны.
Гринго Суаве
Вы можете заставить command.com выполнить команду dos, указав ее в командной строке. См command /c verпротив запуска command.com и ввода вер.
phd443322
Название имеет значение: D Видел много .bat от парней из прошлого! Используйте .cmd! Также не могу поверить, что NT все еще используется сегодня ...
hfrmobile
@hfrmobile: когда я упомянул «NT», я имел в виду, в основном, все версии Windows, основанные на NT (а не 9x). Так что, по сути, NT, Win2k и все версии Windows для рабочего стола или сервера начиная с XP. И имя файла может дать представление о мышлении и стиле кодирования человека, который написал файл, но для интерпретатора нет никакой разницы.
Майкл Барр
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>
tvCa
источник
Это происходит потому, что test.bat находится в алфавитном порядке перед test.cmd. Windows делает жадное завершение.
Дэвид
26
@ Дэвид: Не правда. Это происходит потому, что в PATHEXTпеременной расширение .BAT размещается перед .CMD (как показано в этом ответе). Если вы измените этот порядок в PATHEXT, вместо этого будет выполнен test.cmd.
Аачини
Хм, я надеялся, что они были в другом порядке; Я предполагаю, что MS, должно быть, обнаружила (или предположила), что некоторые существующие программы поставляли файлы .CMD и файлы .BAT с одинаковым базовым именем, где файлы .CMD, конечно, не предназначались в качестве входных данных для (еще не отправленного) cmd. exe, но могло быть и множество других вещей: например, команды для какой-либо другой оболочки, скрипт конфигурации, читаемый приложением, или некоторый двоичный файл приложения. (По крайней мере, это мое понимание обычного способа, которым MS в конечном итоге
ведет себя,
Стоит также отметить, что текущий каталог находится перед другими каталогами в PATHпеременной среды независимо от расширения.
индюк
13

Так как исходный пост касался последствий использования суффикса .bat или .cmd , необязательно команды внутри файла ...

Еще одно отличие между .bat и .cmd заключается в том, что если существуют два файла с одинаковым именем и обоими расширениями, то:

  • ввод имени файла или имени файла .bat в командной строке запустит файл .bat

  • чтобы запустить файл .cmd, вы должны ввести имя файла .cmd

Роб на TVSeries.com
источник
2
А? Если я помещаю cmd-файл в мой каталог, мне не нужно указывать расширение файла, чтобы вызвать его. Пример: echo notepad.exe% *> np.cmd Тогда, если я просто наберу "np mytextfilename.txt", он вызовет блокнот. Мне не нужно вводить «np.cmd», чтобы вызвать его.
Джон Дэвис
2
@ stimpy77: Это верно, если np.cmd является единственным файлом с таким именем, но «если существуют два файла с одинаковым именем файла и обоими этими расширениями» , то единственный способ выполнить .cmd - это включить его расширение. ..
Аасини
1
Это необходимость устранения неоднозначности для любой оболочки, не имеющая ничего общего с техническими различиями между .cmd и .bat. Вероятно, это связано с тем, что filename.bat в алфавитном порядке предшествует filename.cmd.
Джон Дэвис
6
Это на самом деле зависит от PATHEXTпеременной среды. Порядок, в котором появляются расширения, есть порядок приоритета, если расширение не указано. Также стоит упомянуть, что нет необходимости указывать расширение для файлов, которые появляются в переменной env.
Рикардо Зорио
8

все, что работает в пакете, должно работать в cmd; cmd предоставляет некоторые расширения для управления средой. Кроме того, cmd выполняется в новом интерпретаторе cmd и, следовательно, должен быть быстрее (незаметно для коротких файлов) и стабильнее, поскольку bat работает в эмулируемой 16-битной среде NTVDM.

Лоренцо Боккачча
источник
Не должно иметь никакого значения в скорости. .batне работает под DOS в NT. VDM запускается, только если программа нуждается в этом, и даже не поддерживается в 64-битной Windows, хотя я считаю, что .bat есть.
Гринго Суаве
3

Выполнение файлов .cmd и .bat различно, поскольку в переменной .cmd errorlevel он может меняться в команде, на которую влияют расширения команд. Это действительно так.

Zask
источник
Грубый ^. ^ Существуют различия в языке команд, используемых для каждого (.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
1
BAT был создан для взаимодействия с COMMAND.COM, командным интерпретатором DOS. Microsoft приняла большинство команд DOS в своем новом интерпретаторе CMD. EXE. CMD был создан для взаимодействия с CMD.EXE и нарушает совместимость с COMMAND.COM. в основном известен тем, как они обрабатывают переменную errorlevel. При использовании BAT эта переменная изменяется только тогда, когда возникает фактическая ошибка и не происходит никаких изменений в состоянии, когда каждая команда выполняется успешно. Это не верно для CMD, поскольку переменная errorlevel по-прежнему будет менять состояние, даже если ошибок не будет.
Заск
3

Я считаю, что если вы измените значение переменной среды ComSpec на %SystemRoot%system32\cmd.exe(CMD), то не имеет значения, является ли расширение файла .BATили .CMD. Я не уверен, но это может быть даже по умолчанию для WinXP и выше.

Патрик Кафф
источник
1

Немного не по теме, но рассматривали ли вы Windows Scripting Host ? Вы можете найти это лучше.

Marcin
источник
13
В этом отношении PowerShell, который не поддерживает WSH / cscript.exe.
Джон Дэвис
3
@ stimpy77 Правда, хотя powershell мне кажется довольно ужасным.
Марчин
2
Я нахожу WSH намного хуже. Полагаю, все зависит от того, что мы измеряем «ужасным». PowerShell имеет ужасное время запуска. Все об этом абсолютно замечательное ИМО.
Джон Дэвис
Извините за форматирование, но чтобы ускорить время запуска PSH, попробуйте запустить: Set-Alias ​​ngen @ (dir (путь соединения $ {env: \ windir} "Microsoft.NET \ Framework") ngen.exe -recurse | sort -descending lastwritetime) [0] .fullName [НОВАЯ ЛИНИЯ ЗДЕСЬ] [appdomain] :: currentdomain.getassemblies () | % {ngen $ _. location}
mjbnz
1
Совершенно не по теме.
HappyDog
1

Расширение не имеет значения.

Есть небольшие различия между COMMAND.COMобработкой файла против CMD.EXE.

Waldo
источник
-10

разница:

Файлы .cmd загружаются в память перед выполнением. Файлы .bat выполняют строку, читают следующую строку, выполняют эту строку ...

вы можете столкнуться с этим, когда вы выполняете файл сценария, а затем редактируете его, прежде чем он завершится. Файлы bat будут испорчены этим, а файлы cmd - нет.

серый
источник
Как уже было установлено, переменная ComSpec env определяет, какая программа запускается. По сути, вы говорите, что command.com считывает файл по очереди, а cmd.exe предварительно загружает файл в память? Можете ли вы привести ссылку на это?
Крис Но
24
Это неправильно для Vista и XP, оба типа файлов читаются построчно. Если вы приостановите файл .cmd или .bat и отредактируете его, будет выполнен новый код
jeb
1
Можно было бы обсудить, будет ли это строка за строкой, потому что, если вы приостановите выполнение в середине командного файла и добавите символ в начале, после возобновления анализатор будет отключен одним символом, возможно, отбрасывая остальную часть вашего сценария.
2
Вы не должны спорить .bat и .cmd не отличаются таким образом. Оба всегда читаются построчно. Вы можете проверить это, если не верите. Создайте командный файл, который echo 1&pauseзатем выполняет его. Вы увидите 1и Press any key to continue.... Пока пауза добавить новую строку echo 2&pauseс внешним редактором. Нажмите кнопку. Вы увидите 2и Press any key to continue.... Вы даже можете попробовать добавить echo 3&pauseв начале. Когда вы нажмете клавишу после этого снова, вы увидите 2.
Venimus