Looping and variables in a batch file - for-loop

I want to read only first two lines in a batch file and store them in two different variables. I used this code:
#echo off
for /f "delims=''" %%f in (red.txt) do (
echo file is: %%f
set /A Counter+=1
call :a %counter%
echo Counter After Increment: %Counter%
echo.
)
:a
if %Counter% equ 1 (set "file1=%f"
echo first file is: %file1%)
if %Counter% equ 2 (set "file2=%f"
echo second file is: %file2%)
if %Counter% equ 4 exit
echo Counter after for loop: %Counter%
pause
but variables 'file1' and 'file2' show blank.
Any thought on how to go about it?

Your try is a bit overkill and the syntax is wrong.
Try this instead
<red.txt (
set /p line1=
set /p line2=
)
echo line1=%line1%
echo line2=%line2%

Related

Jumping back to label inside loop? [duplicate]

This question already has answers here:
Loop through input parameters and array? [duplicate]
Arrays, linked lists and other data structures in cmd.exe (batch) script
(11 answers)
Closed 2 years ago.
I need to loop through the list of files set through the command line, and loop through a local array.
No knowing of a better way, I tried using labels, but cmd doesn't behave as expected:
#echo off
if "%~1"=="" GOTO PARAM
setlocal enableextensions enabledelayedexpansion
set colors[0]="<style>yellow</style>"
set colors[1]="<style>blue</style>"
set COUNTER=0
for %%f in ("%1") DO (
echo Handling %%f
echo !COUNTER!
:LOOP
IF !COUNTER!=="0" GOTO CASE_YELLOW
IF !COUNTER!=="1" GOTO CASE_BLUE
IF !COUNTER! GTR 6 GOTO END
set /a COUNTER +=1
)
GOTO END
:CASE_YELLOW
ECHO Case YELLOW
GOTO LOOP
:CASE_BLUE
ECHO Case BLUE
GOTO LOOP
:PARAM
echo Usage : %0 myfile.xml/*.xml
:END
ECHO Done.
Here's the output using "myscript.bat file*.xml":
Handling file1.xml
0
Handling fileé.xml
1
Done.
Thank you.
Thankfully you put enough info in your code commenting to kinda see where you were going to with the arguments.
that said, if you want to do something when a condition is met in a loop, and continue with the loop after doing it, you simply need to change to calling your sub Functions, and then end of file which will return tou to your place in the loop.
this should do the needful
#(setlocal enableextensions enabledelayedexpansion
echo off
set "colors[0]=<style>yellow</style>"
set "colors[1]=<style>blue</style>"
set /a "COUNTER=0"
SET "SRC=%~1"
)
IF /I "%~1" EQU "" (
Call :PARAM
) ELSE (
CALL :Main
)
( ENDLOCAL
CALL :End
EXIT /B 0
)
:Main
For %%f in ("%SRC%") DO (
IF !COUNTER! < 6 (
echo Handling %%f
echo !COUNTER!
CALL ECHO.IN MAIN LOOP COLOR= "%%Colors[%counter%]%%"
IF !COUNTER!==0 CALL :CASE_YELLOW
IF !COUNTER!==1 CALL :CASE_BLUE
set /a "COUNTER+=1"
) ELSE (
echo.exiting.
GOTO :EOF
)
)
GOTO :EOF
:CASE_YELLOW
ECHO Case YELLOW
ECHO.In sub function yellow COLOR = "!Colors[%counter%]!"
GOTO :EOF
:CASE_BLUE
ECHO Case BLUE
ECHO.In sub function blue COLOR= "!Colors[%counter%]!"
GOTO :EOF
:PARAM
echo Usage : %0 myfile.xml/*.xml
GOTO :EOF
:END
ECHO Done.
Here's the out
GOTO :EOF

Passing a for parameter inside a variable in a batch script [duplicate]

This question already has an answer here:
Variables are not behaving as expected
(1 answer)
Closed 2 years ago.
set vid1=asd
set vid2=fgh
for /L %%1 in (1,1,2) do (echo %vid%%1%)
pause
doesn't work in my batch file, help
What I need is that cmd resolves first that "%%1" is 1, 2 or whatever; and then resolve %vid1%.
.....................................................................
I think this is a bigger problem, of "variable inside a variable", because this also is not working:
set asd=1
set vid1=qwe
echo %vid%asd%%
I should have used delayedexpansion:
setlocal EnableDelayedExpansion
set vid1=asd
set vid2=qwe
for /L %%i in (1,1,3) do (echo !vid%%i!)
pause
It can also be done without delayedexpansion:
for /L %%1 in (1,1,%count%) do (call :yt "%%vid%%1%%" %%1)
pause
exit
:yt
echo video %2
"C:\[path]\youtube-dl.exe" [youtube-dl arguments] %1
echo.
goto:eof
Full script (it's bloated because I was trying if I could do things):
#echo off
set count=0
:beh
set /a count+=1
set /p vid%count%=vid%count%:
if not defined vid%count% (
set /a count-=1
goto next
) else (
if %count%==1 (echo %count% vid) else (echo %count% vids)
goto beh)
pause
:next
echo %count% videos
pause >nul
choice /m "x?"
IF %ERRORLEVEL% EQU 1 (set x=-x)
echo press enter to run ytdl
pause >nul
echo initiating
echo.
#cd %homepath%/desktop
for /L %%1 in (1,1,%count%) do (call :yt "%%vid%%1%%" %%1)
pause
exit
:yt
echo video %2
"C:\[path]\youtube-dl.exe" %x% --no-check-certificate -w --console-title -i --no-mark-watched -o ".\%%(title)s.%%(ext)s" --prefer-ffmpeg --ffmpeg-location "C:\[ffmpeg path]" %1
echo.
goto:eof

Batch Script Iterative form

I have a batch script which :
check the files in a directory and check if it exists in another
directory and it should not exists there
count each file with a specific format, there should be just one of each
if both of the above statement is true then generate a success file.
Below is my code which is working fine:
SET /A file1=file2=Val=0
SET /A FileE=1
set /a flagname=1
for %%A in (*ABC*.txt) do set /a file1+=1
for %%A in (*XYZ*.txt) do set /a file2+=1
for %%i in ("*") do if exist "Processed\%%~nxi" SET /A FileE=0
SET /A Val=%file1%*%file2%*%FileE%
if %Val% EQU 1 (
echo SUCESS>Sucess.txt
SET Flag=Sucess
echo %Flag%) else (
if %file1% EQU 0 ( echo Missing ABC.txt files >> Error.txt)
if %file1% GTR 1 ( echo More than 1 ABC.txt files >> Error.txt)
if %file2% EQU 0 ( echo Missing XYZ.txt files >> Error.txt)
if %file2% GTR 1 ( echo More than 1 XYZ.txt files >> Error.txt)
(for %%i in ("*") do if exist "Processed\%%~nxi" echo(File Exists in
Processed
Folder %%~i)>>Error.txt
SET Flag=FAILURE
echo %Flag%)
My problem is how to transform above code to iterate over a list of number of files like 100 ? Below is the code which I tried :
#echo off
setlocal enable delayed expansion
Set Filen[0]=ABC*.txt
Set Filen[1]=XYZ*.txt
SET /A Val=1
SET /A File1=0
FOR /l %%G in (0,1,1) Do (
echo !Filen[%%G]! hi
set File1=0
echo %file1% Count
for %%A in (!Filen[%%G]! ) do (
set File1=!File1!+1
echo %%A %file1%)
)
Put your search words in a string and iterate over it:
Set "Search=ABC DEF XYZ"
For %%A in (%Search%) do (
Or in a file and read one by one
For /f "usebackq" %%A in ("Search.txt") Do (
With this file Search.txt
ABC
DEF
XYZ
In the environment
> tree a:\ /F
Auflistung der Ordnerpfade für Volume RamDisk
A:\
└───Test
│ ABC_123.txt
│ DEF_456.txt
│ Search.txt
│
└───Processed
The following batch
:: Q:\Test\2018\07\01\SO_51120147.cmd
#Echo off & Setlocal EnableDelayedExpansion
Set "BaseDir=A:\Test"
Set Err=^>^> "Error.txt" Call Echo=[%%date%% %%time%%]
PushD "%BaseDir%" || (%Err% can't locate %BaseDir% & Pause &Goto :Eof)
%Err% Job %~f0 started by %USERNAME%
Set " Flag=Sucess"
:: Uncomment for string variant
:: Set "Search=ABC DEF XYZ"
:: For %%A in (%Search%) do (
:: use the file variant
For /f "usebackq" %%A in ("Search.txt") Do (
Set Cnt=0
For %%B in (%%A*.txt) Do Set /A Cnt=1
if !Cnt! NEQ 1 (
%Err% Count of %%A*.txt file=[!Cnt!]
SET Flag=FAILURE
)
)
For %%A in (*) do if exist "Processed\%%~nxA" (
%Err% File %%A does exist in Processed Folder
Set Flag=FAILURE
)
%Err% Job %~f0 terminated with %Flag%
Yields this output:
> type A:\Test\Error.txt
[2018-07-01 13:10:34,43] Job Q:\Test\2018\07\01\SO_51120147.cmd started by LotPings
[2018-07-01 13:10:34,45] Count of XYZ*.txt file=[0]
[2018-07-01 13:10:34,47] Job Q:\Test\2018\07\01\SO_51120147.cmd terminated with FAILURE
EDIT: Explanation of the somehow tricky line:
Set Err=^>^> "Error.txt" Call Echo=[%%date%% %%time%%]
To not have to pre/append every line which should go to the error log with
the redirection and a (fixed) file name I put these together with the
echo command and a [date time] stamp into a variable.
To avoid immediate interpretation when setting the variable, the '>' have to
be esaped with a caret, and to delay the expansion of the %-signs these have
to be doubled. (otherwise each log entry had the same date time)
To force expansion of date time when echoing the (pseudo) call is neccessary.

How to use % or ! in batch script

I write script like this:
#ECHO OFF
setlocal EnableDelayedExpansion
set "remove=ABC"
echo. %remove%
Set FILENAME="456_789_ABC00011092_789_EFGHIK_56893.mpg"
for %%a in (%FILENAME:_=" "%) do (
set TEN=%%a
echo. %AB%
set "remove_1=ABC"
echo. %remove_1%
Set _TEN=!TEN:%remove%=!
echo. %_TEN%
Set i=0
IF !_TEN! NEQ !TEN! (
set /A i+=1
set "String[!i!]=%%~a"
)
)
pause
exit
Why echo. %AB% echo. %remove_1% result is
I replace % by !. It's work fine but command Set _TEN=!TEN:!remove_1!=! not run
Edit - (from the additional question currently posted as an answer)
When I use FindStr command like this:
for %%a in (%FILENAME:_=" "%) do (
echo %%a | findstr /I /R /C:"ABC" >nul
ECHO %errorlevel%
if "%errorlevel%" equ "0" (
set /A i+=1
set "String[!i!]=%%~a"
)
)
Why errorlevel always = 0
%AB% has not been defined within your posted script, so as it has no value will not be echoed, you will just get an empty line due to the . after echo. Because remove_1 is being set within the loop, (code block), you should be using the delayed expansion syntax, Echo !remove_1!. It is the same for echo. %_TEN%, i.e. Echo !_TEN!, and would have been Echo !AB! had it previously been defined. In order to get the double expansion needed to Set your _TEN variable, you could use a pseudo Call:
#Echo Off
SetLocal EnableDelayedExpansion
Set "FILENAME=456_789_ABC00011092_789_EFGHIK_56893.mpg"
For %%A In ("%FILENAME:_=" "%") Do (
Set "TEN=%%A"
Echo. !AB!
Set "remove_1=ABC"
Echo !remove_1!
Call Set "_TEN=!TEN:%%remove_1%%=!"
Echo !_TEN!
Set "i=0"
If "!_TEN!" NEq "!TEN!" (
Set /A i+=1
Set "String[!i!]=%%~A"
)
)
Pause
Exit /B
In your second related question, initially posted as an answer and now added as an edit to your original question; because the error level is being set within the loop, (code block), you should be using the delayed expansion syntax, !errorlevel!
#Echo Off
SetLocal EnableDelayedExpansion
Set "FILENAME=456_789_ABC00011092_789_EFGHIK_56893.mpg"
For %%A In ("%FILENAME:_=" "%") Do (
Echo %%A | FindStr /IRC:"ABC" >Nul
Echo !errorlevel!
If "!errorlevel!"=="0" (
Set /A i+=1
Set "String[!i!]=%%~A"
)
)
Set String[
Pause
Exit /B
Or if you don't need to Echo each error level to the screen, you can use a conditional statement &&:
#Echo Off
SetLocal EnableDelayedExpansion
Set "FILENAME=456_789_ABC00011092_789_EFGHIK_56893.mpg"
For %%A In ("%FILENAME:_=" "%") Do (
Echo %%A | FindStr /IRC:"ABC" >Nul && (
Set /A i+=1
Set "String[!i!]=%%~A"
)
)
Set String[
Pause
Exit /B

how to do loop in Batch?

I want to create something like this
dup.bat infile outfile times
example usage would be
dup.bat a.txt a5.txt 5
at it would create file a5.txt that has the content of a.txt repeated 5 times
however I do not know how to do for loop in batch, how to do it?
You can do the loop like this:
SET infile=%1
SET outfile=%2
SET times=%3
FOR /L %%i IN (1,1,%times%) DO (
REM do what you need here
ECHO %infile%
ECHO %outfile%
)
Then to take the input file and repeat it, you could use MORE with redirection to append the contents of the input file to the output file. Note this assumes these are text files.
#ECHO off
SET infile=%1
SET outfile=%2
SET times=%3
IF EXIST %outfile% DEL %outfile%
FOR /L %%i IN (1,1,%times%) DO (
MORE %infile% >> %outfile%
)
For command line args
set input=%1
set output=%2
set times=%3
To do a simple for loop, read in from the input file, and write to the output file:
FOR /L %%i IN (1,1,%times%) DO (
FOR /F %%j IN (%input%) DO (
#echo %%j >> %output%
)
)
Instead of taking in an output file, you could also do it via command line:
dup.bat a.txt 5 > a5.txt
sigh
Compact Design:
SETLOCAL ENABLEDELAYEDEXPANSION
SET times=5
:Beginning
IF %times% NEQ 0 (TYPE a.txt>>a5.txt & SET /a times=%times%-1 & GOTO Beginning) ELSE ( ENDLOCAL & set times= & GOTO:eof)
Easy Reading:
SETLOCAL ENABLEDELAYEDEXPANSION
SET times=5
:Beginning
IF %times% NEQ 0 (
TYPE a.txt>>a5.txt
SET /a times=%times%-1
GOTO Beginning
) ELSE (
ENDLOCAL
set times=
GOTO:eof
)
Set your counter (times=5)
Start subroutine Beginning
If your counter doesn't equal 0, read a.txt and APPEND its contents to a5.txt, then decrement your counter by 1. This will repeat five times until your counter equals 0, then it will cleanup your variable and end the script.
SET ENABLEDELAYEDEXPANSION is important to increment variables within loops.

Resources