Обработка условий в пакетных программах.
if [not ] errorlevel число команда [ else выражение ]
if [not ] строка1 == строка2 команда [ else выражение ]
if [not ] exist имя_файла команда [ else выражение ]
Если расширения командного процессора разрешены, следует использовать следующий синтаксис:
if [/i ] строка1 оп_сравнения строка2 команда [else выражение ]
if cmdextversion число команда [else выражение ]
if defined переменная команда [else выражение ]
При использовании команды defined переменная добавляются следующие три переменные: %errorlevel% , %cmdcmdline% и %cmdextversion% .
%errorlevel% errorlevel , если только уже не существует переменная среды с именем ERRORLEVEL. В этом случае будет использовано ее значение. В следующем примере показано использование значения errorlevel после выполнения пакетной программы:
goto answer%errorlevel%
:answer0
echo Код возврата программы равен 0
:answer1
echo Код возврата программы равен 1
goto end
:end
echo Готово!
Операторы сравнения оп_сравнения также можно использовать следующим образом:
If %errorlevel% LEQ 1 goto okay
%cmdcmdline% замещается исходной командной строкой, переданной Cmd.exe, до ее обработки в Cmd.exe, если только уже не существует переменная среды с именем cmdcmdline . В этом случае будет использовано значение cmdcmdline .
%cmdextversion% замещается строковым представлением текущего значения cmdextversion , если только уже не существует переменная среды с именем CMDEXTVERSION. В этом случае будет использовано ее значение.
Оператор else должен размещаться в той же строке, что и команда if . Пример:
IF EXIST имя_файла. (del имя_файла.) ELSE (echo имя_файла. отсутствует.)
del должна заканчиваться новой строкой:
IF EXIST имя_файла. del имя_файла. ELSE echo имя_файла. отсутствует
Приведенный ниже пример не будет работать, поскольку команда else должна находиться в той же строке, что и команда if :
IF EXIST имя_файла. del имя_файла. ELSE echo имя_файла. отсутствует
Если необходимо разместить всю инструкцию в одной строке, можно использовать следующую правильную форму исходной инструкции:
IF EXIST имя_файла (del имя_файла) ELSE echo имя_файла отсутствует
Если файл Product.dat не удается найти, появится следующее сообщение:
if not exist product.dat echo Не найден файл данных
Если в приведенном ниже примере при форматировании диска в дисководе A возникнет ошибка, будет выведено сообщение об ошибке:
:begin
@echo off
format a: /s
if not errorlevel 1 goto end
echo Ошибка при форматировании.
:end
echo Конец пакетной программы.
Если ошибка не возникнет, сообщение об ошибке выведено не будет.
Команда if не может быть использована непосредственно для проверки существования каталога, но в каждом каталоге существует устройство (NUL). Следовательно, существование каталога может быть проверено, как показано ниже. В следующем примере проверяется наличие каталога:
if exist c:mydir\nul goto process
Для вопросов, обсуждений, замечаний, предложений и т. п. можете использовать раздел форума этого сайта (требуется регистрация).
Формат командной строки:
IF ERRORLEVEL число команда
IF строка1==строка2 команда
IF EXIST имя_файла команда
Параметры:
NOT - Указывает, что Windows должна выполнить эту команду, только если условие является ложным.
ERRORLEVEL число - Условие является истинным, если код возврата последней выполненной программы не меньше указанного числа.
строка1==строка2 - Условие является истинным, если указанные строки совпадают.
EXIST имя_файла - Условие является истинным, если файл с указанным именем существует.
команда - Задает команду, выполняемую при истинности условия. За этой командой может следовать ключевое слово ELSE. В случае, если указанное условие ложно, будет выполнена команда, находящаяся после слова ELSE.
Предложение ELSE должно располагаться в той же строке, что и команда, следующая за ключевым словом IF. Например:
IF EXIST имя_файла. (
del имя_файла.
) ELSE (
echo имя_файла. missing.
)
Следующий пример содержит ОШИБКУ, поскольку команда del должна заканчиваться переходом на новую строку:
IF EXIST имя_файла. del имя_файла. ELSE echo имя_файла. Missing
Следующий пример также содержит ОШИБКУ, поскольку команда ELSE должна располагаться в той же строке, что и команда, следующая за IF:
IF EXIST имя_файла. del имя_файла.
ELSE echo имя_файла. missing
Вот правильный пример, где все команды расположены в одной строке:
IF EXIST имя_файла. (del имя_файла.) ELSE echo имя_файла. Missing
Изменение команды IF при включении расширенной обработки команд:
IF строка1 оператор_сравнения строка2 команда
IF CMDEXTVERSION число команда
IF DEFINED переменная команда
Где оператор_сравнения принимает следующие значения:
EQU
- равно
NEQ
- не равно
LSS
- меньше
LEQ
- меньше или равно
GTR
- больше
GEQ
- больше или равно,
А ключ /I , если он указан, задает сравнение текстовых строк без учета регистра. Ключ /I можно также использовать и в форме строка1==строка2 команды IF. Сравнения проводятся по общему типу данных, так что если строки 1 и 2 содержат только цифры, то обе строки преобразуются в числа, после чего выполняется сравнение чисел.
Условие CMDEXTVERSION применяется подобно условию ERRORLEVEL, но значение сравнивается с внутренним номером версии текущей реализации расширенной обработки команд. Первая версия имеет номер 1. Номер версии будет увеличиваться на единицу при каждом добавлении существенных возможностей расширенной обработки команд. Если расширенная обработка команд отключена, условие CMDEXTVERSION никогда не бывает истинно.
Условие DEFINED применяется подобно условию EXIST , но принимает в качестве аргумента имя переменной среды и возвращает истинное значение, если эта переменная определена.
Строка %ERRORLEVEL% будет развернута в строковое представление текущего значения кода ошибки ERRORLEVEL, за исключением ситуации, когда уже имеется переменная среды с именем ERRORLEVEL; в подобном случае подставляется значение этой переменной. Например, с помощью данной строки можно выполнить следующее:
goto answer%ERRORLEVEL%
:answer0
echo Получен код возврата 0
:answer1
echo Получен код возврата 1
Допускается и применение описанных выше операторов числового сравнения:
IF %ERRORLEVEL% LEQ 1 goto okay
Строка %CMDCMDLINE% будет развернута в исходную командную строку, переданную CMD.EXE до любой обработки, за исключением ситуации, когда уже определена переменная среды с именем CMDCMDLINE; в подобном случае подставляется значение этой переменной.
Строка %CMDEXTVERSION% будет развернута в строку, представляющую собой текущее значение CMDEXTVERSION, за исключением ситуации, когда уже имеется переменная среды с именем CMDEXTVERSION; в подобном случае подставляется значение этой переменной.
Примеры использования:
Если параметр командной строки не задан, то пользователю выдается сообщение об ошибке.
@echo off
REM Проверить наличие имени файла, задаваемого в качестве параметра %1
REM Если параметр %1 пустой – переход на метку error
if "%1" EQU "" goto error
REM Если параметр задан, создаем пустой файл, копированием из устройства nul
copy nul "%1"
exit
:error
ECHO File name required ! Must be - %~n0 filename.ext
:exit
Примеры вывода для отвечающего и не отвечающего узлов:
Ответ от 192.168.1.1: число байт=32 время=1мс TTL=64
- если устройство с данным IP-адресом доступно;
Превышен интервал ожидания для запроса.
- если устройство не отвечает;
Команда find /I "TTL"
возвращает код ERRORLEVEL равный 0
, если строка
"TTL" присутствует в результате выполнения ping
. Ключ /I
имеет смысл использовать,
чтобы результат не зависил от того, строчные или заглавные символы составляют строку "ttl".
Результат работы командного файла записывается в текстовый файл iplist.txt
@ECHO OFF
REM Постоянная часть IP-адреса
set IPTMP=192.168.1.
REM Количество пингуемых узлов
set N=254
rem С какого адреса начать - начальное значение " хвоста " IP- адреса X.X.X.IPMIN
set /A IPMIN=1
ECHO %DATE% Опрос пингом %N% адресов начиная с %IPTMP%%IPMIN% >> iplist.txt
rem M0 - метка для организации цикла
:M0
rem Переменная IPFULL - полное значение текущего IP-адреса
set IPFULL=%IPTMP%%IPMIN%
rem Если " хвост "больше N – перейти к завершению работы
IF %IPMIN% GTR %N% GOTO ENDJOB
ping -n 1 %IPFULL% | find /I "TTL"
if %ERRORLEVEL%==0 Echo %IPFULL% >> iplist.txt
rem Сформируем следующий IP-адрес
set /A IPMIN=%IPMIN% + 1
rem Перейдем на выполнение следующего шага
GOTO M0
rem Завершение работы
:endjob
exit
Существуют некоторые особенности реализации командного интерпретатора CMD.EXE , которые необходимо учитывать при обработке значений переменных внутри циклов IF и FOR . Использование значений переменных внутри скобок, требует изменения стандартного режима интерпретации командного процессора. Разработчиками предусмотрена возможность запуска CMD.EXE с параметром /V:ON , что включает разрешение отложенного расширения переменных среды с применением символа восклицательного знака (! ) в качестве разделителя. То есть, параметр /V:ON разрешает использовать !var! в качестве значения переменной var во время выполнения внутри циклов команд FOR и IF . Но на практике чаще используется возможность локального включения данного режима внутри командного файла специальной директивой:
Setlocal EnableDelayedExpansion
После чего, можно обрабатывать принимаемые переменными значения внутри цикла, используя вместо знаков процента восклицательные знаки:
FOR … (
IF !ERRORLEVEL!==0
вместо %ERRORLEVEL%==0
…
)
    В русскоязычной справке команды IF имеется ошибка, которая много лет переходит из версии в версию - вместо оператора EQU - равно , указано EQL - равно
Обработка условий в пакетных программах
if [not ] errorlevel число команда [ else выражение ]
if [not ] строка1 == строка2 команда [ else выражение ]
if [not ] exist имя_файла команда [ else выражение ]
Если расширения командного процессора разрешены, следует использовать следующий синтаксис:
if [/i ] строка1 оп_сравнения строка2 команда [else выражение ]
if cmdextversion число команда [else выражение ]
if defined переменная команда [else выражение ]
/i Сравнение строк без учета регистра знаков. Параметр /i можно использовать в конструкции string1 == string2 команды if . Эти сравнения являются общими. Если и строка1 , и строка2 состоят из цифр, строки преобразовываются в числа и выполняется сравнение чисел. cmdextversion число Условие выполняется, только если номер внутренней версии, связанный с расширениями командного процессора Cmd.exe, равен или больше числа . первая версия имела номер 1. Номер версии увеличивается на 1 при внесении в расширения командного процессора значительных изменений. Условие с cmdextversion не выполняется, если расширения командного процессора запрещены (по умолчанию они разрешены). defined переменная Условие выполняется, если переменная определена. выражение Команда и все ее параметры для обработке в командной строке при выполнении оператора else . /? Отображение справки в командной строке.
При использовании команды defined переменная добавляются следующие три переменные: %errorlevel% , %cmdcmdline% и %cmdextversion% .
%errorlevel% errorlevel , если только уже не существует переменная среды с именем ERRORLEVEL. В этом случае будет использовано ее значение. В следующем примере показано использование значения errorlevel после выполнения пакетной программы:
goto answer%errorlevel% :answer0 echo Код возврата программы равен 0:answer1 echo Код возврата программы равен 1 goto end:end echo Готово!
Операторы сравнения оп_сравнения также можно использовать следующим образом:
if %errorlevel% LEQ 1 goto okay
%cmdcmdline% замещается исходной командной строкой, переданной Cmd.exe, до ее обработки в Cmd.exe, если только уже не существует переменная среды с именем cmdcmdline . В этом случае будет использовано значение cmdcmdline .
%cmdextversion% замещается строковым представлением текущего значения cmdextversion , если только уже не существует переменная среды с именем CMDEXTVERSION. В этом случае будет использовано ее значение.
Оператор else должен размещаться в той же строке, что и команда if . Пример:
IF EXIST имя_файла. (del имя_файла.) ELSE (echo имя_файла. отсутствует.)
del должна заканчиваться новой строкой:
IF EXIST имя_файла. del имя_файла. ELSE echo имя_файла. отсутствует
Приведенный ниже пример не будет работать, поскольку команда else должна находиться в той же строке, что и команда if :
IF EXIST имя_файла. del имя_файла. ELSE echo имя_файла. отсутствует
Если необходимо разместить всю инструкцию в одной строке, можно использовать следующую правильную форму исходной инструкции:
IF EXIST имя_файла (del имя_файла) ELSE echo имя_файла отсутствует
Если файл Product.dat не удается найти, появится следующее сообщение:
if not exist product.dat echo Не найден файл данных
Если в приведенном ниже примере при форматировании диска в дисководе A возникнет ошибка, будет выведено сообщение об ошибке:
:begin @echo off format a: /s if not errorlevel 1 goto end echo Ошибка при форматировании. :end echo Конец пакетной программы.
Если ошибка не возникнет, сообщение об ошибке выведено не будет.
Команда if не может быть использована непосредственно для проверки существования каталога, но в каждом каталоге существует устройство (NUL). Следовательно, существование каталога может быть проверено, как показано ниже. В следующем примере проверяется наличие каталога:
if exist c:mydir\nul goto process
Обработка условий в пакетных программах.
if [not ] errorlevel число команда [ else выражение ]
if [not ] строка1 == строка2 команда [ else выражение ]
if [not ] exist имя_файла команда [ else выражение ]
Если расширения командного процессора разрешены, следует использовать следующий синтаксис:
if [/i ] строка1 оп_сравнения строка2 команда [else выражение ]
if cmdextversion число команда [else выражение ]
if defined переменная команда [else выражение ]
При использовании команды defined переменная добавляются следующие три переменные: %errorlevel% , %cmdcmdline% и %cmdextversion% .
%errorlevel% errorlevel , если только уже не существует переменная среды с именем ERRORLEVEL. В этом случае будет использовано ее значение. В следующем примере показано использование значения errorlevel после выполнения пакетной программы:
goto answer%errorlevel%
:answer0
echo Код возврата программы равен 0
:answer1
echo Код возврата программы равен 1
goto end
:end
echo Готово!
Операторы сравнения оп_сравнения также можно использовать следующим образом:
If %errorlevel% LEQ 1 goto okay
%cmdcmdline% замещается исходной командной строкой, переданной Cmd.exe, до ее обработки в Cmd.exe, если только уже не существует переменная среды с именем cmdcmdline . В этом случае будет использовано значение cmdcmdline .
%cmdextversion% замещается строковым представлением текущего значения cmdextversion , если только уже не существует переменная среды с именем CMDEXTVERSION. В этом случае будет использовано ее значение.
Оператор else должен размещаться в той же строке, что и команда if . Пример:
IF EXIST имя_файла. (del имя_файла.) ELSE (echo имя_файла. отсутствует.)
del должна заканчиваться новой строкой:
IF EXIST имя_файла. del имя_файла. ELSE echo имя_файла. отсутствует
Приведенный ниже пример не будет работать, поскольку команда else должна находиться в той же строке, что и команда if :
IF EXIST имя_файла. del имя_файла. ELSE echo имя_файла. отсутствует
Если необходимо разместить всю инструкцию в одной строке, можно использовать следующую правильную форму исходной инструкции:
IF EXIST имя_файла (del имя_файла) ELSE echo имя_файла отсутствует
Если файл Product.dat не удается найти, появится следующее сообщение:
if not exist product.dat echo Не найден файл данных
Если в приведенном ниже примере при форматировании диска в дисководе A возникнет ошибка, будет выведено сообщение об ошибке:
:begin
@echo off
format a: /s
if not errorlevel 1 goto end
echo Ошибка при форматировании.
:end
echo Конец пакетной программы.
Если ошибка не возникнет, сообщение об ошибке выведено не будет.
Команда if не может быть использована непосредственно для проверки существования каталога, но в каждом каталоге существует устройство (NUL). Следовательно, существование каталога может быть проверено, как показано ниже. В следующем примере проверяется наличие каталога:
if exist c:mydir\nul goto process
Нет стандартного способа делать пакетные файлы, потому что подавляющее большинство их авторов и сопровождающих либо не понимают концепций программирования, либо считают, что они не применяются к пакетным файлам.
Но я программист. Я привык к компиляции, и я привык к отладчикам. Пакетные файлы не скомпилированы, и вы не можете запускать их через отладчик, поэтому они заставляют меня нервничать. Я предлагаю вам быть более строгим в отношении того, что вы пишете, поэтому вы можете быть уверены, что он будет делать то, что, по вашему мнению, делает.
Существуют некоторые стандарты кодирования, которые говорят: если вы пишете оператор if , вы должны использовать фигурные скобки, даже если у вас нет предложения else . Это избавляет вас от тонких, трудно отлаживаемых проблем и недвусмысленно читается. Я не вижу причин, по которым вы не могли применить это рассуждение к пакетным файлам.
Посмотрите на свой код.
IF EXIST somefile.txt IF EXIST someotherfile.txt SET var=somefile.txt,someotherfile.txt
И синтаксис if , из команды HELP IF:
IF ERRORLEVEL number command IF string1==string2 command IF EXISTS filename command ... IF EXIST filename (command) ELSE (other command)
Итак, вы цепляете if как команды.
Если вы используете стандартное правило стандартного кодирования, о котором я упоминал выше, вы всегда хотели бы использовать parens. Вот как вы могли бы сделать это для своего примера кода:
IF EXIST "somefile.txt" (IF EXIST "someotherfile.txt" (SET var="somefile.txt,someotherfile.txt"))
Удостоверьтесь, что вы четко форматируете и выполняете какую-то форму отступа. Вы делаете это в коде, и вы должны делать это в своих пакетных сценариях.
Кроме того, вы также должны иметь привычку всегда ссылаться на ваши имена файлов и получать право на цитаты. Существует несколько слов в HELP FOR и HELP SET , которые помогут вам удалить лишние кавычки при повторном цитировании строк.
Из ваших комментариев и повторного чтения исходного вопроса кажется, что вы хотите создать список файлов, разделенных запятыми, которые существуют. В этом случае вы можете просто использовать кучу операторов if / else , но это приведет к кучке дублированной логики и не будет чистым, если у вас более двух файлов.
Лучше всего написать подпрограмму , которая проверяет существование одного файла и добавляет к переменной, если указанный файл существует, Затем просто вызовите эту подпрограмму для каждого файла, который вы хотите проверить.