Почему не работает errorlevel в цикле
Сообщения: 53036
Благодарности: 15396
| Конфигурация компьютера | |
| Процессор: AMD Ryzen 7 7800X3D | |
| Материнская плата: Gigabyte B650E Aorus Master | |
| Память: Kingston Fury Renegade DDR5-6000 32GB (2×16) | |
| HDD: Samsung SSD 850 PRO 256GB, 980 PRO 1TB | |
| Видеокарта: Gainward GeForce RTX 3080 追风 | |
| Блок питания: be quiet! Straight Power 11 650W | |
| Монитор: ASUS VG248QE 24″ | |
| ОС: Windows 10 Pro x64 | |
| Прочее: корпус Fractal Design Define R4 |
setlocal enabledelayedexpansion for /f "skip=1 tokens=1,2 delims=|" %%i in (%1) do ( for /f "delims=" %%k in (%%i.txt) do ( something.exe %%k %%i echo !errorlevel! ) )
EnableDelayedExpansion — позднее связывание.
Это сообщение посчитали полезным следующие участники:
Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.
Сообщения: 1025
Благодарности: 180
| Конфигурация компьютера | |
А к переменным, заключенным в !! можно применять разные :~0,-1?
——-
echo 127.0.0.1 google.ru >> %systemroot%\system32\drivers\etc\hosts && ipconfig /flushdns && echo Я ничего не трогал, оно само!
Сообщения: 27449
Благодарности: 8086
Цитата apozlevich:
| А к переменным, заключенным в !! можно применять разные :~0,-1? » |
Это сообщение посчитали полезным следующие участники:
Сообщения: 26
Благодарности: 1
Подниму тему.
есть листинг:
@ECHO off @COLOR 4 @CHCP 866 SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION CLS :Start For /F "Tokens=2*" %%I In ('Reg Query "HKCU\Software\Microsoft\Shared\UcClient" /V ConfigurationMode') Do SET key=%%J IF %ERRORLEVEL%==0 ( echo 1 pause ) echo 0 pause
просто ищет по реестру ключ.
ключ есть — %errorlevel%=0
ключа нет- %errorlevel%=0 но в консоли пишет, что «ошибка-мол, нет такого» значит место указано верно
как заставить реагировать %errorlevel% на наличие\отсутствие ключа в реестре?
Сообщения: 27449
Благодарности: 8086
Instant_SR, в данном случае Вы видите errorlevel от команды «for /f».
Цитата Instant_SR:
| как заставить реагировать %errorlevel% на наличие\отсутствие ключа в реестре? » |
@echo off setlocal enableextensions enabledelayedexpansion for /f "usebackq tokens=2*" %%i in ( `reg.exe query "HKCU\Software\Microsoft\Shared\UcClient" /v "ConfigurationMode" 2^>nul ^| find.exe /i "ConfigurationMode"` ) do set sConfigurationMode=%%j if defined sConfigurationMode ( echo ConfigurationMode: [%sConfigurationMode%]. ) else ( echo Parameter not exists. ) endlocal exit /b 0
Почему не работает errorlevel в цикле
почему-то не увеличивается переменная CNT
rem Обработка файла c настройками echo workin with cfg-file: "%SETTINGSFILE%" rem счетчик каталогов из файла настроек copy.cfg set CNT=0 for /f "eol=# delims== tokens=1,2" %%i in (%SETTINGSFILE%) do ( set /a CNT+=1 echo %CNT%: %%i=%%j ) exit /b 0
вывод в консоль:
-
I:\>copy.bat
workin with cfg-file: «copy.cfg»
1: dir=»programs_x»
1: dir=»projects»
1: dir=»learn»
1: dir=»base»
Re: батник, как в цикле увеличивать счетчик?
| От: | Аноним |
| Дата: | 26.11.07 22:00 |
| Оценка: |
Разобрался, надо было так:
for /f "eol=# delims== tokens=1,2" %%i in (%SETTINGSFILE%) do ( set /a CNT+=1 echo !CN1: %%i=%%j )
и запуск интерпретатора команд Windows XP с /V
Re: батник, как в цикле увеличивать счетчик?
| От: | Кодт | |
| Дата: | 27.11.07 10:33 | |
| Оценка: | 2 (1) | |
Здравствуйте, <Аноним>, Вы писали:
А>почему-то не увеличивается переменная CNT
Проблема не в том, что она не увеличивается, а в том, что она однократно подставляется в вывод.
Нужно делать так:
Аноним>
@echo off setlocal enabledelayedexpansion set cnt=0 set foo=f set bar=b for /l %%n in (1,1,10) do ( set /a cnt+=10 set foo=%foo%f set bar=!bar!b echo %%n : !cnt! versus %cnt%; !foo! and !bar! ) echo %cnt%, %foo%, %bar%
1 : 10 versus 0; ff and bb 2 : 20 versus 0; ff and bbb 3 : 30 versus 0; ff and bbbb 4 : 40 versus 0; ff and bbbbb 5 : 50 versus 0; ff and bbbbbb 6 : 60 versus 0; ff and bbbbbbb 7 : 70 versus 0; ff and bbbbbbbb 8 : 80 versus 0; ff and bbbbbbbbb 9 : 90 versus 0; ff and bbbbbbbbbb 10 : 100 versus 0; ff and bbbbbbbbbbb 100, ff, bbbbbbbbbbb
Потому что тело цикла — сперва развёртывается с подстановкой всех переменных, а уже потом интерпретируется.
Перекуём баги на фичи!
Re[2]: батник, как в цикле увеличивать счетчик?
| От: | Аноним |
| Дата: | 28.11.07 13:49 |
| Оценка: |
не включается режим (
SETLOCAL ENABLEDELAYEDEXPANSION IF NOT %ERRORLEVEL%==0 echo Can't enable
Re[3]: батник, как в цикле увеличивать счетчик?
| От: | Аноним |
| Дата: | 28.11.07 13:54 |
| Оценка: |
Здравствуйте, Аноним, Вы писали:
А>не включается режим (
А>
А>SETLOCAL ENABLEDELAYEDEXPANSION А>IF NOT %ERRORLEVEL%==0 echo Can't enable А>
натупил у меня там call : стоял, поэтому пропускал, и == не нужно было ставить
Команда SETLOCAL — изменение переменных среды для текущего командного файла.
    Команда SETLOCAL используется для временного изменения значений переменных среды в командных файлах Windows. Изменения среды, внесенные после выполнения команды SETLOCAL, являются локальными относительно текущего пакетного файла. Для восстановления их прежних значений необходимо выполнить команду ENDLOCAL. При достижении конца пакетного файла автоматически выполняется команда ENDLOCAL для всех действующих команд SETLOCAL, выполненных в этом пакетном файле и значения всех переменных окружения восстанавливаются к состоянию до выполнения команды SETLOCAL.
Формат командной строки:
SETLOCAL | ENABLEDELAYEDEXPANSION | DISABLEDELAYEDEXPANSION
Изменение команды SETLOCAL при включении расширенной обработки команд:
Команда SETLOCAL принимает необязательные аргументы: ENABLEEXTENSIONS или DISABLEEXTENSIONS. Это позволяет включить или отключить расширенную обработку команд до выполнения команды. См. CMD /? для подробного объяснения. ENABLEDELAYEDEXPANSION / DISABLEDELAYEDEXPANSION включает или отключает отложенное расширение переменной среды. См. SET /? для подробного объяснения. Эти изменения действуют до совпадения команды ENDLOCAL, независимо от исходного состояния до вызова команды SETLOCAL.
Если команда SETLOCAL вызывается с аргументом, она устанавливает код ошибки ERRORLEVEL. Если указан один из двух допустимых аргументов, код ошибки будет равен нулю, иначе возвращается значение 1. Это свойство можно использовать в пакетных файлах, чтобы определить доступность расширенной обработки команд, например:
VERIFY OTHER 2>nul
SETLOCAL ENABLEEXTENSIONS
IF ERRORLEVEL 1 echo Не удается включить расширенную обработку
Эта группа команд работает, так как в прежних версиях CMD.EXE команда SETLOCAL не устанавливает значение ERRORLEVEL. Команда VERIFY с недопустимым аргументом необходима для установки ненулевого значения ERRORLEVEL.
При использовании переменных окружения в командных файлах существует определенное ограничение, связанное с тем фактом, что присваиваемое значение остается без изменения при его модификации внутри группы команд, задаваемой скобками, например в командах IF или FOR . Для обхода данного ограничения используется запуск командного процессора с параметром /V:ON и вместо знаков процента, для получения принимаемого переменной значения, используются восклицательные знаки. Кроме того, существует возможность использовать стандартный запуск командного процессора, но с локальным включением данного режима командой :
Разница в результатах использования значений переменных довольно наглядно демонстрируется следующим командным файлом:
Setlocal EnableDelayedExpansion
@ECHO OFF
set VAR=before
if «%VAR%» == «before» (
set VAR=after
if «!VAR!» == «after» @echo Со знаком процента=%VAR% , Со знаком вопроса=!VAR!
)
Команда set VAR=after выполняется внутри подпрограммы, ограниченной скобками и, если убрать команду Setlocal EnableDelayedExpansion или не использовать для получения значения переменной VAR восклицательные знаки, ее значение останется старым ( тем, что было установлено до входа в подпрограмму ). Аналогичная же проблема наблюдается и тогда, когда значение переменной изменяется внутри цикла команды FOR . Например, для получения списка файлов текущего каталога такой командный файл не будет работать:
set LIST=
for %%i in (*) do set LIST=%LIST% %%i
echo %LIST%
Значение переменной LIST внутри цикла изменено не будет. Для того, чтобы это произошло, командный файл нужно изменить следующим образом:
Setlocal EnableDelayedExpansion
set LIST=
for %%i in (*) do set LIST=!LIST! %%i
echo %LIST%
Теперь, значение переменной LIST внутри цикла FOR будет изменяться, последовательно принимая значения имен файлов, разделенных пробелом ( set LIST=!LIST! %%i )
IF – оператор условного выполнения команд в командных файлах Windows
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 [/I] строка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 . Но на практике чаще используется возможность локального включения данного режима внутри командного файла специальной директивой:
После чего, можно обрабатывать принимаемые переменными значения внутри цикла, используя вместо знаков процента восклицательные знаки:
FOR … (
IF !ERRORLEVEL!==0 вместо %ERRORLEVEL%==0
…
)
    В русскоязычной справке команды IF имеется ошибка, которая много лет переходит из версии в версию — вместо оператора EQU — равно , указано EQL — равно