Пакетный файл — это файл сценария в DOS , OS/2 и Microsoft Windows . Он состоит из ряда команд , которые должны быть выполнены интерпретатором командной строки , и хранится в текстовом файле. Пакетный файл может содержать любую команду, которую интерпретатор принимает интерактивно, и использовать конструкции, которые позволяют выполнять условные ветки и циклы в пакетном файле, например IF
, FOR
, и GOTO
метки . Термин «пакет» происходит от пакетной обработки , что означает «неинтерактивное выполнение», хотя пакетный файл может не обрабатывать пакет из нескольких данных.
Подобно Job Control Language (JCL), DCL и другим системам на мэйнфреймах и миникомпьютерных системах, пакетные файлы были добавлены для облегчения работы, необходимой для определенных регулярных задач, позволяя пользователю настроить сценарий для их автоматизации. Когда запускается пакетный файл, программа оболочки (обычно COMMAND.COM или cmd.exe ) считывает файл и выполняет его команды, обычно построчно. [1] Unix-подобные операционные системы , такие как Linux , имеют похожий, но более гибкий тип файла, называемый скриптом оболочки . [2]
Расширение имени файла .bat используется в DOS и Windows. Windows NT и OS/2 также добавили .cmd . Пакетные файлы для других сред могут иметь другие расширения, например, .btm в оболочках 4DOS , 4OS2 и 4NT .
Подробная обработка пакетных файлов значительно изменилась между версиями. Некоторые детали в этой статье применимы ко всем пакетным файлам, в то время как другие детали применимы только к определенным версиям.
В MS-DOS пакетный файл можно запустить из интерфейса командной строки, введя его имя, а затем любые требуемые параметры и нажав ↵ Enterклавишу. При загрузке DOS файл AUTOEXEC.BAT , если он присутствует, выполняется автоматически, поэтому любые команды, которые необходимо выполнить для настройки среды DOS, можно поместить в этот файл. Пользователи компьютеров могут использовать файл AUTOEXEC.BAT для установки системной даты и времени, инициализации среды DOS, загрузки любых резидентных программ или драйверов устройств или инициализации сетевых подключений и назначений.
Расширение имени файла .bat идентифицирует файл, содержащий команды, которые выполняются интерпретатором команд COMMAND.COM построчно, как если бы это был список команд, введенных вручную, с некоторыми дополнительными командами, специфичными для пакетного файла, для основных функций программирования, включая GOTO
команду для изменения потока выполнения строк.
Microsoft Windows была представлена в 1985 году как графический пользовательский интерфейс (GUI) поверх текстовых операционных систем и была разработана для работы в DOS. Для ее запуска WIN
использовалась команда, которую можно было добавить в конец файла AUTOEXEC.BAT , чтобы разрешить автоматическую загрузку Windows. В более ранних версиях можно было запустить файл типа .bat из Windows в командной строке MS-DOS. Windows 3.1x и более ранние версии, а также Windows 9x вызывали COMMAND.COM для запуска пакетных файлов.
Операционная система IBM OS/2 поддерживала пакетные файлы в стиле DOS. Она также включала версию REXX , более продвинутого языка сценариев пакетных файлов . IBM и Microsoft начали разрабатывать эту систему, но во время ее создания расстались из-за спора; в результате IBM ссылалась на свою консольную оболочку в стиле DOS без упоминания Microsoft, называя ее просто DOS, хотя это, по-видимому, не имело никакого значения в отношении того, как пакетные файлы работали из COMMAND.COM.
Интерпретатор пакетных файлов OS/2 также поддерживает команду EXTPROC. Она передает пакетный файл в программу, указанную в файле EXTPROC, как файл данных. Указанная программа может быть файлом сценария; это похоже на механизм #!, используемый в операционных системах типа Unix .
В отличие от Windows 98 и более ранних версий, семейство операционных систем Windows NT не зависит от MS-DOS. Windows NT представила усовершенствованный 32-разрядный интерпретатор команд ( cmd.exe ), который мог выполнять скрипты с расширением .CMD или .BAT. Cmd.exe добавил дополнительные команды и реализовал существующие немного другим способом, так что один и тот же пакетный файл (с другим расширением) может работать по-разному с cmd.exe и COMMAND.COM. В большинстве случаев работа идентична, если не используются несколько неподдерживаемых команд. Расширения Cmd.exe для COMMAND.COM можно отключить для совместимости.
Microsoft выпустила версию cmd.exe для Windows 9x и ME под названием WIN95CMD, чтобы позволить пользователям старых версий Windows использовать определенные пакетные файлы в стиле cmd.exe.
Начиная с Windows 8 [обновлять], cmd.exe является обычным интерпретатором команд для пакетных файлов; более старый COMMAND.COM также может быть запущен в 32-разрядных версиях Windows, способных запускать 16-разрядные программы. [примечание 1]
append
, dpath
, ftype
, set
, path
, assoc
и prompt
при выполнении из файла .bat изменяют значение переменной errorlevel
только при возникновении ошибки, тогда как из файла .cmd они будут влиять на errorlevel даже при возврате без ошибки. [3] Он также используется в OS/2 IBM для пакетных файлов.COMMAND.COM и cmd.exe поддерживают специальные переменные ( от %0
, %1
до %9
) для ссылки на путь и имя пакетного задания и первые девять параметров вызова из пакетного задания, см. также SHIFT. Несуществующие параметры заменяются строкой нулевой длины. Их можно использовать аналогично переменным среды , но они не хранятся в среде. Microsoft и IBM называют эти переменные параметрами замены или заменяемыми параметрами , тогда как Digital Research, Novell и Caldera ввели для них термин переменные замены [5] . JP Software называет их параметрами пакетного файла . [6]
В этом примере пакетный файл отображает Hello World!
, запрашивает и ждет, пока пользователь нажмет клавишу, а затем завершает работу. (Примечание: не имеет значения, являются ли команды строчными или заглавными, если только не работают с переменными)
@ ECHO OFF ECHO Привет, мир! ПАУЗА
Чтобы выполнить файл, его необходимо сохранить с расширением .bat (или .cmd для операционных систем типа Windows NT) в формате простого текста, обычно создаваемого с помощью текстового редактора, такого как Microsoft Notepad , или текстового процессора, работающего в режиме простого текста.
При выполнении отобразится следующее:
Привет, мир!Нажмите любую клавишу, чтобы продолжить...
Интерпретатор выполняет каждую строку по очереди, начиная с первой. @
Символ в начале любой строки не позволяет подсказке отображать эту команду по мере ее выполнения. Команда ECHO OFF
отключает подсказку навсегда или до тех пор, пока она не будет включена снова. Объединенная @ECHO OFF
часто, как здесь, является первой строкой пакетного файла, предотвращая отображение любых команд, включая ее саму. Затем выполняется следующая строка, и команда ECHO Hello World!
выводит Hello World!
. Выполняется следующая строка, и PAUSE
команда отображает Press any key to continue . . .
и приостанавливает выполнение скрипта. После нажатия клавиши скрипт завершается, так как больше нет команд. В Windows, если скрипт выполняется из уже запущенного окна командной строки , окно остается открытым в подсказке, как в MS-DOS; в противном случае окно закрывается по завершении.
Расширения переменных подставляются текстуально в команду, и таким образом переменные, которые ничего не содержат, просто исчезают из синтаксиса, а переменные, которые содержат пробелы, превращаются в несколько токенов. Это может привести к синтаксическим ошибкам или багам.
Например, если %foo% пуст, этот оператор:
IF %foo% == bar ECHO Равно
анализируется как ошибочная конструкция:
ЕСЛИ ==bar ECHO Равно
Аналогично, если %foo%
содержит abc def
, то возникает другая синтаксическая ошибка:
ЕСЛИ abc def == bar ECHO Равно
Обычный способ предотвратить эту проблему — заключить расширения переменных в кавычки, чтобы пустая переменная расширялась в допустимое выражение IF ""=="bar"
вместо недопустимого IF ==bar
. Текст, который сравнивается с переменной, также должен быть заключен в кавычки, поскольку кавычки не являются специальным разделительным синтаксисом; эти символы представляют сами себя.
ЕСЛИ " %foo% " == "bar" ECHO Равно
Отложенное расширение !VARIABLE!, доступное в Windows 2000 и более поздних версиях, может использоваться для избежания этих синтаксических ошибок. В этом случае переменные null или multiword не терпят синтаксической ошибки, поскольку значение расширяется после разбора команды IF:
IF !foo! == bar ECHO Равно
Другое отличие в Windows 2000 или выше заключается в том, что пустая переменная (неопределенная) не подставляется. Как описано в предыдущих примерах, предыдущее поведение пакетного интерпретатора привело бы к пустой строке. Пример:
C:\> set MyVar = C:\> echo %MyVar% %MyVar%C:\> если " %MyVar% " == "" ( echo MyVar не определена ) else ( echo MyVar это %MyVar% ) MyVar это %MyVar%
Пакетные интерпретаторы до Windows 2000 отображали результат MyVar is not defined
.
В отличие от процессов Unix/POSIX, которые получают аргументы командной строки, уже разделенные оболочкой на массив строк, процесс Windows получает всю командную строку как одну строку через функцию API GetCommandLine. В результате каждое приложение Windows может реализовать свой собственный парсер для разделения всей командной строки на аргументы. Многие приложения и инструменты командной строки разработали собственный синтаксис для этого, и поэтому не существует единого соглашения для кавычек или экранирования метасимволов в командных строках Windows.
cmd.exe
и wscript.exe
, используют свои собственные правила. [8]Если строка содержит кавычки и должна быть вставлена в другую строку текста, которая также должна быть заключена в кавычки, необходимо уделить особое внимание механизму кавычек:
C:\> set foo = "эта строка заключена в кавычки"C:\> echo "test 1 %foo% " "test 1 "эта строка заключена в кавычки""C:\> eventcreate /T Предупреждение /ID 1 /L Система /SO "Источник" /D "Пример: %foo% " ОШИБКА: Недопустимый аргумент/параметр - 'string'. Введите "EVENTCREATE /?" для использования.
В Windows 2000 и более поздних версиях решение заключается в замене каждого вхождения символа кавычек в значении серией из трех символов кавычек:
C:\> set foo = "эта строка заключена в кавычки"C:\> set foo = %foo:"="""%C:\> echo "test 1 %foo% " "test 1 """эта строка заключена в кавычки""""C:\> eventcreate /T Warning /ID 1 /L System /SO "Источник" /D "Пример: %foo% " УСПЕХ: Событие типа "Предупреждение" создано в журнале/источнике "Источник".
Некоторые символы, такие как |
символы вертикальной черты ( ), имеют особое значение в командной строке. Их нельзя напечатать как текст с помощью команды ECHO , если только они не экранированы с помощью символа вставки ^:
C:\> echo foo | bar «bar» не является внутренней или внешней командой, исполняемой программой или пакетным файлом.C:\> echo foo ^| bar foo | bar
Однако экранирование не работает так, как ожидалось, когда в переменную окружения вставляется экранированный символ. Переменная в итоге содержит команду живого конвейера, когда просто выводится на экран. Необходимо экранировать как саму каретку, так и экранированный символ, чтобы символ отображался как текст в переменной:
C:\> set foo = bar | baz «baz» не является внутренней или внешней командой, исполняемой программой или пакетным файлом.C:\> set foo = bar ^| baz C:\> echo %foo% 'baz' не является внутренней или внешней командой, исполняемой программой или пакетным файлом.C:\> set foo = bar ^^^| baz C:\> echo %foo% bar | Баз
Отложенное расширение, доступное в Windows 2000 и более поздних версиях, может использоваться для отображения специальных символов, хранящихся в переменных среды, поскольку значение переменной расширяется после анализа команды:
C:\> cmd /V:ON Microsoft Windows [Версия 6.1.7601] Авторские права (c) 2009 Microsoft Corporation. Все права защищены.C:\> set foo = bar ^| baz C:\> echo !foo! бар | Баз
До появления команды TIMEOUT в Windows Vista не существовало простого способа реализовать временную паузу, поскольку команда PAUSE останавливает выполнение скрипта на неопределенный срок до тех пор, пока не будет нажата какая-либо клавиша.
Было возможно множество обходных путей [10], но они работали только в некоторых средах: CHOICE
команда была недоступна в старых версиях DOS, PING
была доступна только при установленном TCP/IP и т. д. Microsoft не предлагала никакого решения, но ряд небольших служебных программ можно было установить из других источников. Коммерческим примером может служить команда Norton Utilities Batch Enhancer (BE) 1988 года, которая BE DELAY 18
ждала 1 секунду, или бесплатная 94-байтовая WAIT.COM [11] , которая WAIT 5
ждала 5 секунд, а затем возвращала управление сценарию. Большинство таких программ представляют собой 16-битные файлы .COM, поэтому они несовместимы с 64-битной Windows.
Обычно весь печатный текст автоматически содержит управляющие символы возврата каретки (CR) и перевода строки (LF), добавляемые в конец каждой строки.
@ эхо фу @ эхо бар
C:\> batchtest.bat foo bar
Не имеет значения, находятся ли две команды echo в одной и той же командной строке; коды CR/LF вставляются для разбиения вывода на отдельные строки:
C:\> @ echo Сообщение 1 &@ echo Сообщение 2 Сообщение 1 Сообщение 2
Трюк, обнаруженный в Windows 2000 и более поздних версиях, заключается в использовании специального приглашения для ввода для вывода текста без CR/LF, завершающих текст. В этом примере CR/LF не следует за сообщением 1, но следует за строкой 2 и строкой 3:
@ echo off set /p = "Сообщение 1" < nul echo Сообщение 2 echo Сообщение 3
C:\> batchtest2.bat Сообщение 1Сообщение 2 Сообщение 3
Это можно использовать для вывода данных в текстовый файл без добавления CR/LF в конец:
C:\> set /p = "Сообщение 1" < nul > data.txt C:\> set /p = "Сообщение 2" < nul >> data.txt C:\> set /p = "Сообщение 3" < nul >> data.txt C:\> type data.txt Сообщение 1Сообщение 2Сообщение 3
Однако нет возможности напрямую внедрить этот урезанный вывод приглашения CR/LF в переменную среды.
Невозможно иметь командную строку, которая использует UNC-путь в качестве текущего рабочего каталога; например\\server\share\directory\
Командная строка требует использования букв дисков для назначения рабочего каталога, что затрудняет запуск сложных пакетных файлов, хранящихся на общем ресурсе UNC сервера. Хотя пакетный файл можно запустить из пути к файлу UNC, рабочим каталогом по умолчанию является C:\Windows\System32\
.
В Windows 2000 и более поздних версиях обходным решением является использование команды PUSHD
и POPDс расширениями команд. [примечание 2]
Если расширения команд не включены по умолчанию, их можно временно включить с помощью /E:ON
переключателя для интерпретатора команд.
Таким образом, чтобы запустить пакетный файл на общем ресурсе UNC, назначить временную букву диска для общего ресурса UNC и использовать общий ресурс UNC в качестве рабочего каталога пакетного файла, можно создать ярлык Windows, который выглядит следующим образом:
Атрибут рабочего каталога этого ярлыка игнорируется.
Это также решает проблему, связанную с контролем учетных записей пользователей (UAC) в Windows Vista и более новых версиях. Когда администратор вошел в систему и UAC включен, и он пытается запустить пакетный файл как администратор из буквы сетевого диска, используя контекстное меню файла, вызываемое правой кнопкой мыши, операция неожиданно завершается ошибкой. Это происходит из-за того, что контекст учетной записи с повышенными правами UAC не имеет назначений букв сетевых дисков, и невозможно назначить буквы дисков для повышенного контекста через оболочку проводника или сценарии входа. Однако, создав ярлык для пакетного файла с помощью приведенной выше конструкции PUSHD
/ POPD
и используя ярлык для запуска пакетного файла как администратор, временная буква диска будет создана и удалена в контексте учетной записи с повышенными правами, и пакетный файл будет работать правильно.
Следующий синтаксис правильно расширяется до пути текущего пакетного скрипта.
%~dp0
Пути UNC по умолчанию отключены, поскольку они приводили к сбоям в работе старых программ. [12]
Значение реестра Dword DisableUNCCheck
в HKEY_CURRENT_USER\Software\Microsoft\Command Processor
[12] позволяет использовать каталог по умолчанию в качестве UNC. CD
Команда откажется вносить изменения, но можно поместить путь UNC в каталог по умолчанию с помощью ярлыка Cmd или с помощью команды «Пуск». ( C$
Share предназначен для администраторов).
Пакетные файлы используют набор символов OEM, как определено компьютером, например, кодовая страница 437. Не-ASCII части этих файлов несовместимы с наборами символов Unicode или Windows, которые в противном случае используются в Windows, поэтому необходимо соблюдать осторожность. [13] Неанглийские имена файлов работают только если они введены через редактор, совместимый с набором символов DOS. Имена файлов с символами вне этого набора не работают в пакетных файлах.
Чтобы получить командную строку с Unicode вместо кодовой страницы 437 или аналогичной, можно использовать cmd /U
команду. В такой командной строке будет работать пакетный файл с именами файлов в Unicode. Также можно использовать cmd /U
для прямого выполнения команд с Unicode в качестве набора символов. Например, cmd /U /C dir > files.txt
создает файл, содержащий список каталогов с правильными символами Windows в кодировке UTF-16 LE.
Как и в случае с любым другим языком программирования, пакетные файлы могут использоваться злонамеренно. Простые трояны и форк-бомбы легко создаются, а пакетные файлы могут выполнять форму отравления DNS , изменяя файл hosts . Пакетные вирусы возможны и могут также распространяться через USB-флешки , используя функцию автозапуска Windows . [14]
Следующая команда в пакетном файле удалит все данные в текущем каталоге (папке) — без предварительного запроса подтверждения:
дель /Q *.*
Эти три команды представляют собой простую форк-бомбу , которая будет постоянно воспроизводить себя, истощая доступные системные ресурсы, замедляя или вызывая сбой системы:
: TOP начать "" %0 перейти к TOP
Командный процессор cmd.exe, который интерпретирует файлы .cmd, поддерживается во всех 32-разрядных версиях Windows вплоть до Windows 10 и 64-разрядных версиях Windows вплоть до Windows 11. COMMAND.EXE, который интерпретирует файлы .BAT, поддерживался во всех 16-разрядных и 32-разрядных версиях, как минимум, до Windows 10. [примечание 3]
Существуют и другие, более поздние и более мощные языки сценариев, доступные для Windows. Однако для их использования требуется установить интерпретатор языка сценариев:
Файлы скриптов запускаются, если введено имя файла без расширения. Существуют правила приоритета, регулирующие интерпретацию, скажем, DoThis
если существуют DoThis.com
, DoThis.exe
, DoThis.bat
, , и т. д.; по умолчанию имеет наивысший приоритет. Этот порядок по умолчанию может быть изменен в более новых операционных системах с помощью устанавливаемой пользователем переменной среды PATHEXT .DoThis.cmd
DoThis.com
COMMAND.COM
в командной строке 32-разрядной Windows 7.Две последовательные двойные кавычки внутри области inQuotes должны привести к буквальной двойной кавычке (анализатор остается в области inQuotes). Такое поведение не является частью спецификации code:ParseArgumentsIntoList, но совместимо с CRT и .NET Framework.