Цикл с условием bat file. Цикл bat for


[CMD] Циклические операции и примеры (команда FOR)

Продолжение...

Особенности, которые распространяются на циклы FOR

0) Если нужно записать в наборе несколько команд, то используем:

а) знаки амперсанда &, если мы хотим записать все в одну строку:

Код:

FOR /L %%a IN (1,1,10) DO echo Найден файл:& echo %%a б) знаки скобок, если хотим разбить команды в несколько строк для наглядности и удобства:

Код:

FOR /L %%a IN (1,1,10) DO ( echo Найден файл: echo %%a ) 1) Пустые строки в содержимом файлов и выводе команд игнорируются.

2) Если предполагается получение пустого токена, остальные токены смещаются.К примеру,имеем файл с содержимым:

file.txt написал(а):

Применим команду:

Код:

FOR /F "tokens=1,2,3 delims=/" %%a in (file.txt) do echo a=%%a; b=%%b; c=%%c Результат будет:вместо ожидаемого3) Все специальные (служебные) символы необходимо экранировать (предварять птичкой ^). Это такие символы, как | = ^ &. А также % ! - если они используются не для раскрытия переменной, кроме случая с !, когда не включено удаленное расширение переменных. Сюда же входит знак кавычки, которая соответствует форме кавычки, применяемой для определения вида набора.

4) Регистр переменной цикла имеет значение.

5) Изменить вручную значение переменной цикла нельзя. Например, set %%A=param не даст эффекта.

6) После выхода из цикла переменная цикла уничтожается.

7) Внутри цикла можно использовать не более 1-го комментария вида :: (иначе, будет критическая ошибка и "вылет" из пакетного файла)Вместо этого используем Rem.

8) Внутри цикла можно использовать не более 1-й метки (иначе, будет такой же "вылет").

Пример максимально допустимой конструкции:

Код:

@echo off for %%n in ( 0 1 2 3 4 5 6 7 8 9 ) do ( :label echo %%n :: comment echo %%n ) 9) Тем не менее из цикла можно безвозвратно выйти на метку Goto metka а также выйти в подпрограмму и вернутся снова в цикл точно в ту же позицию через команду Call :metka В конце подпрограммы должна стоять команда Exit /B

10) Для получения значения обычной переменной внутри цикла в случае, если этой переменной было присвоено новое значение внутри тела этого же цикла, необходимо раскрывать переменную через знаки восклицания !variant! - это называется отложенное расширение переменных.Перед использованием такого способа, его нужно включить, задав в начале пакетного файла команду:

Код:

SetLocal EnableDelayedExpansion Иначе, если использовать обычный способ раскрытия %variant%, мы получим значение переменной, присвоенное ей еще до входа в цикл. Точно таким же образом (через ! ) необходимо раскрывать переменную времени внутри цикла, т.к. иначе для цикла время "замерзает". Происходит это потому, что в цикл попадает т.н. "слепок" переменных среды. И работа с ними через % происходит уже как с копией данных, а не актуальными значениями.

11) Когда после IN указана команда, под разбор цикла попадают такие потоки:1-й поток (StdOut)с 3-го по 9-й поток (User Stream)

При этом 2-й поток (StdError) отображается на экране сразу после выполнения указанной в цикле команды в IN (...)2-й поток можно занулить, обычным способом, не забыв экран:

Код:

FOR /F %%A IN ('dir %someparam% 2^>nul') do rem Также можно перенаправить 2-й поток, чтобы он обрабатывался вместе с первым, вместо его вывода на экран:

Код:

FOR /F %%A IN ('dir %someparam% 2^>^&1') do rem Собственно, чтобы наоборот, обрабатывать 2-й поток вместо первого, можно воспользоваться следующей конструкцией:

Код:

FOR /F %%A IN ('dir %someparam% 1^>nul 2^>^&3') do rem 12) При запуске цикла из консоли (cmd.exe) переменные цикла нужно указывать без удвоения знака процента %a. Это же правило касается вызова цикла через Shell-подобные команды на других языках программирования.

13) Переменную цикла нельзя раскрыть внутри строки модификаторов другого цикла:

for /f %%q in (quote) do for /f "usebackq tokens=1* delims=%%q" %%a in ("%~dp01.txt") do echo %%a%%b

но есть способ обхода от ComSpec: Спойлер Как известно, значение переменной цикла нельзя просто подставить в качестве модификатора в другой, вложенный, цикл:

Код:

for /f "tokens=2" %i in ("1 3 5") do @for /f "tokens=%i" %j in ("1 3 5 7 9") do @echo %j Результатом такой подстановки будет вывод ошибки: [quote] Непредвиденное появление: %i". [/quote] Если же сделать так: [code] for /f "tokens=2" %i in ("1 3 5") do @set x=%i for /f "tokens=%x%" %j in ("1 3 5 7 9") do @echo %j то ошибки не будет:Но как всё же осуществить корректный вывод во вложенном цикле?

Если попробовать присвоить какой-нибудь переменной значение переменной первого цикла, а эатем запустить второй цикл с этой переменной в новом экземпляре интерпретатора с включённым отложенным расширением, то ошибка не исчезает:

Код:

for /f "tokens=2" %i in ("1 3 5") do @set x=%i& cmd/v/c for /f "tokens=!x!" %j in ("1 3 5 7 9") do @echo %j результат:

Непредвиденное появление: !x!".

Оказалось, что это можно сделать проще, а именно просто запустить вложенный цикл в новом экземпляре интерпретатора:

Код:

for /f "tokens=2" %i in ("1 3 5") do @cmd/c for /f "tokens=%i" %j in ("1 3 5 7 9") do @echo %j результат:

safezone.cc

Цикл с условием bat file

Первое условие срабатывает, а остальные не срабатывают. Хотя по логике все должно работать. Батник вызывается с параметрами: my.bat -d 123 -dh 333

:while if "%1"=="-d" ( set WORKDIR=%2 & shift & shift & goto :while ) if "%1"=="--work-dir" ( set WORKDIR="%2" & shift & shift & goto :while ) if "%1"=="-l"( set LOGDIR="%2" & shift & shift & goto :while) if "%1"=="-log-dir"( set LOGDIR="%2" & shift & shift & goto :while) if "%1"=="-dh"( set DBHOST="%2" & shift & shift & goto :while) if "%1"=="--host"( set DBHOST=%2 & shift & shift & goto :while) if "%1"=="-db"( set DATABASE=%2 & shift & shift & goto :while) if "%1"=="--database"( set DATABASE=%2 & shift & shift & goto :while) if "%1"=="-u"( set DBUSER=%2 & shift & shift & goto :while) if "%1"=="--db-user"( set DBUSER=%2 & shift & shift & goto :while) if "%1"=="-p"( set DBPASSWORD=%2 & shift & shift & goto :while) if "%1"=="--db-password"( set DBPASSWORD=%2 & shift & shift & goto :while) if "%1"=="-j"( set JOBS=%2 & shift & shift & goto :while) if "%1"=="--jobs"( set JOBS=%2 & shift & shift & goto :while) if "%1"=="-ld"( set LOGDROP=%2 & shift & shift & goto :while) if "%1"=="--log-drop"( set LOGDROP=%2 & shift & shift & goto :while) if "%1"=="-pt"( set PROJECTSTYPE=%2 & shift & shift & goto :while) if "%1"=="--projects-type"( set PROJECTSTYPE=%2 & shift & shift & goto :while) if "%1"=="-pn"( set PROJECTNAME=%2 & shift & shift & goto :while) if "%1"=="--projects-name"( set PROJECTNAME=%2 & shift & shift & goto :while) if "%1"=="-jc"( set JOBSBATCH=%2 & shift & shift & goto :while) if "%1"=="--jobs-batch"( set JOBSBATCH=%2 & shift & shift & goto :while) if "%1"=="-def"( set DEFAULT=YES & shift & goto :while) if "%1"=="-default"( set DEFAULT=YES & shift & goto :while) if "%1"==""(set /a POSITIONAL+=%1 & shift & goto :endwhile) :endwhile

Полный код скрипта:

wmic csproduct get "UUID">mac.txt echo %UUID% SET /P UUID=<mac.txt set file = mac.txt set old = "UUID" more +1 "mac.txt" >"file.txt.new" move /y "file.txt.new" "mac.txt" >nul SET /P UUID=<mac.txt rem For /F "usebackq tokens=* skip=1 delims=" %%i In (%file%) Do Set UUID=%%i echo %UUID% pause :uniqLoop set "WORKDIR=\bat~%RANDOM%.tmp" if exist "%WORKDIR%" goto :uniqLoop echo >"%WORKDIR%" :: Запись переменной в файл для проверки echo %perem% set LOGDIR="./Logs" set LOGDROP=NO set DBHOST=localhost set DATABASE=DAE set DBUSER=root set DBPASSWORD=1 set JOBS=0.8 set PROJECTSTYPE=* set PROJECTNAME=* set JOBSRECHECK=5 set JOBSBATCH=100 set DEFAULT=NO for %%a in (%CD%) do set /a cnt+=1 REM echo %cnt% rem ## worker_start.sh -d tmp - l set f_sr="-d" set POSITIONAL=() :while pause echo %1 echo %2 pause if "%1"=="-d" ( set WORKDIR=%2 & shift & shift & goto :while ) if "%1"=="--work-dir" ( set WORKDIR="%2" & shift & shift & goto :while ) if "%1"=="-l"( set LOGDIR="%2" & shift & shift & goto :while) if "%1"=="-log-dir"( set LOGDIR="%2" & shift & shift & goto :while) if "%1"=="-dh"( set DBHOST="%2" & shift & shift & goto :while) if "%1"=="--host"( set DBHOST=%2 & shift & shift & goto :while) if "%1"=="-db"( set DATABASE=%2 & shift & shift & goto :while) if "%1"=="--database"( set DATABASE=%2 & shift & shift & goto :while) if "%1"=="-u"( set DBUSER=%2 & shift & shift & goto :while) if "%1"=="--db-user"( set DBUSER=%2 & shift & shift & goto :while) if "%1"=="-p"( set DBPASSWORD=%2 & shift & shift & goto :while) if "%1"=="--db-password"( set DBPASSWORD=%2 & shift & shift & goto :while) if "%1"=="-j"( set JOBS=%2 & shift & shift & goto :while) if "%1"=="--jobs"( set JOBS=%2 & shift & shift & goto :while) if "%1"=="-ld"( set LOGDROP=%2 & shift & shift & goto :while) if "%1"=="--log-drop"( set LOGDROP=%2 & shift & shift & goto :while) if "%1"=="-pt"( set PROJECTSTYPE=%2 & shift & shift & goto :while) if "%1"=="--projects-type"( set PROJECTSTYPE=%2 & shift & shift & goto :while) if "%1"=="-pn"( set PROJECTNAME=%2 & shift & shift & goto :while) if "%1"=="--projects-name"( set PROJECTNAME=%2 & shift & shift & goto :while) if "%1"=="-jc"( set JOBSBATCH=%2 & shift & shift & goto :while) if "%1"=="--jobs-batch"( set JOBSBATCH=%2 & shift & shift & goto :while) if "%1"=="-def"( set DEFAULT=YES & shift & goto :while) if "%1"=="-default"( set DEFAULT=YES & shift & goto :while) if "%1"==""(set /a POSITIONAL+=%1 & shift & goto :endwhile) :endwhile echo "Hello, while is over" echo "Worker start with options:" echo %UUID% echo %WORKDIR% echo %LOGDIR% echo %LOGDROP% echo %DBHOST% echo %DATABASE% echo %DBUSER% echo %DBPASSWORD% echo %JOBS% echo %PROJECTSTYPE% echo %PROJECTNAME% echo %JOBSRECHECK% echo %JOBSBATCH% echo %DEFAULT% echo %POSITIONAL% python worker_start.py --work-dir %WORKDIR% --log-dir %LOGDIR% -dh %DBHOST% -db %DATABASE% -u %DBUSER% -p %DBPASSWORD% -j %JOBS% -ld %LOGDROP% -pt %PROJECTSTYPE% -pn %PROJECTNAME% -jc %JOBSRECHECK% -jb %JOBSBATCH% -def %DEFAULT% --UUID %UUID% pause

ru.stackoverflow.com

Цикл Bat

Вопрос: Генерация случайного числа в теле цикла FOR

Добрый день подскажите пожалуйста как правильно вставить код генерации случайного числа внутрь цикла for чтобы он работал.

Цикл:

Windows Batch file
1 for /l %%i in (1,1,10) do echo %%i
Код генерации случайного числа:
Windows Batch file
1 2 3 set minimum=0 set maximum=10 set /a number=%random%%%(maximum-minimum+1)+minimum
И как корректно отнять единицу от счетчика %%i в теле цикла чтобы он выполнился на один круг больше. Ответ:

Сообщение от AlexDF

Отредактируйте пожалуйста ваш пример, чтобы после кода: ...В каждой итерации выполнялся код:

Хмм, а то, что это бессмысленное действие - ничего? Вот тут:

Сообщение от YuS_2

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

- я пытался описать проблему, которая присутствует в Вашем коде. Ещё один, последний разок: Если Вам необходимо одно единственное, рандомное значение переменной, то совсем необязательно помещать этот код в цикл - это абсолютно бесполезная трата ресурсов. Если Вам необходимо несколько рандомных значений переменной, то для того, чтобы создать приемлемый код в цикле, необходимо описание конечной цели использования переменных. Иначе никак, только к телепатам.

Добавлено через 8 минутВот, вам расширенная версия (со свистелками-моргалками в консоли, чтобы не было скучно при ожидании заполнения нулевого файл-флага ) предыдущего моего кода:

Windows Batch file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @echo off :: Создать 10 файлов если проверочный файл непустой, иначе прогрессбар в 30 символов set count=0 set con= set cnt=0 setlocal enabledelayedexpansion     :reset if !cnt! gtr 30 (cls&&set /a cnt=0) :begin if !count! lss 10 ( for /f %%i in ('forfiles /p "C:\temp" /m temp.txt /c "cmd /c echo @fsize"') do (     if "%%i" gtr "0" (         set /a count+=1         if !count!==1 (cls)         echo create file!count!&&echo.>"C:\temp\!count!.txt"&&goto :begin     ) else (         set /a cnt+=1         set /p con=в–’<nul         timeout /t 1 >nul         goto :reset         )     ) ) pause
А с рандомом - попробуйте самостоятельно подумать, как его добавить в цикл. Но учтите, что именно так, как предлагаете Вы, добавлять его, всё равно, нет смысла.

Добавлено через 3 минуты

Сообщение от YuS_2

в–’

- здесь, в 18 строке, был символ псевдографики, его движок форума съел. Туда можно добавлять другой, какой больше понравится.

forundex.ru