windows batch script - setting variable inside for loop - windows

maybe i'm not representing my question clear, here's the actual code i did:
#echo off
set /p keywords="Enter keywords to search: " %=%
dir /b *.dat > filelist.txt
for /f "delims=." %%f in (filelist.txt) do (
for /f "delims= " %%g in (%%f.dat) do (
7z e %%g *sec.evtx
dir /b *.evtx > evtfile.txt
set /p tmpvar1=<evtfile.txt
del *.evtx
)
)
filelist.txt
tsnint1.dat
webint1.dat
tsnint1.dat
TSNINT1-201312091700.zip
TSNINT1-201312091600.zip
TSNINT1-201312091500.zip
TSNINT1-201312091400.zip
TSNINT1-201312091300.zip
TSNINT1-201312091200.zip
webint1.dat
WEBINT1-201312091300.zip
WEBINT1-201312091200.zip
the problem i'm facing is, evtfile consists of the right content but tmpvar1 is not assigned correctly as expected, what is my mistake and how to correct it? many thanks

You need delayed expansion to use a variable inside a block when this variable has been set (or changed) inside the same block. But you can set a variable without delayed expansion.
See this little demonstration (I used a simple if construct instead of for, but the effect is the same (not with if or for, but with blocks (inside ( and )).
#echo off
REM SETTING a variable inside a block
set "var=ONE"
echo start: %var%
if 1==1 (
echo inside block: %var%
set var=TWO
echo var has a new value:
set var
echo inside block is still old: %var%
)
echo after block: %var%
echo ----------
REM USING a variable inside a block
setlocal enabledelayedexpansion
set "var=ONE"
echo start: %var%
if 1==1 (
echo inside block: %var%
set var=TWO
echo var has a new value:
set var
echo new value inside block: !var!
echo just to demonstrate: %var%
)
echo after block: %var%
endlocal
echo ----------
echo working fine: %var%
echo not available after endlocal: !var!

This might help, using your code as a base. FWIW I hope that you have more than one copy of the .evtx files, if they are important to you.
#echo off
setocal enabledelayedexapnsion
for /f "delims=" %%f in ('dir /b *.dat') do (
for /f "delims=" %%g in ('type "%%f" ') do (
7z e "%%g" "*sec.evtx"
dir /b *.evtx > evtfile.txt
set /p tmpvar1=<evtfile.txt
echo !tempvar!
del *.evtx
)
)
One issue is that the *.evtx files are being deleted after the first archive is created, so the subsequent ones will have nothing to archive.

Related

Batch String +=? [duplicate]

I made this code
dir /B /S %RepToRead% > %FileName%
for /F "tokens=*" %%a in ('type %FileName%') do (
set z=%%a
echo %z%
echo %%a
)
echo %%a is working fine but echo %z% returns "echo disabled".
I need to set a %z% because I want to split the variable like %z:~7%
Any ideas?
There are two methods to setting and using variables within for loops and parentheses scope.
setlocal enabledelayedexpansion see setlocal /? for help. This only works on XP/2000 or newer versions of Windows.
then use !variable! instead of %variable% inside the loop...
Create a batch function using batch goto labels :Label.
Example:
for /F "tokens=*" %%a in ('type %FileName%') do call :Foo %%a
goto End
:Foo
set z=%1
echo %z%
echo %1
goto :eof
:End
Batch functions are very useful mechanism.
You probably want SETLOCAL ENABLEDELAYEDEXPANSION. See https://devblogs.microsoft.com/oldnewthing/20060823-00/?p=29993 for details.
Basically: Normal %variables% are expanded right aftercmd.exe reads the command. In your case the "command" is the whole
for /F "tokens=*" %%a in ('type %FileName%') do (
set z=%%a
echo %z%
echo %%a
)
loop. At that point z has no value yet, so echo %z% turns into echo. Then the loop is executed and z is set, but its value isn't used anymore.
SETLOCAL ENABLEDELAYEDEXPANSION enables an additional syntax, !variable!. This also expands variables but it only does so right before each (sub-)command is executed.
SETLOCAL ENABLEDELAYEDEXPANSION
for /F "tokens=*" %%a in ('type %FileName%') do (
set z=%%a
echo !z!
echo %%a
)
This gives you the current value of z each time the echo runs.
I struggeld for many hours on this.
This is my loop to register command line vars.
Example : Register.bat /param1:value1 /param2:value2
What is does, is loop all the commandline params,
and that set the variable with the proper name to the value.
After that, you can just use
set value=!param1!
set value2=!param2!
regardless the sequence the params are given. (so called named parameters).
Note the !<>!, instead of the %<>%.
SETLOCAL ENABLEDELAYEDEXPANSION
FOR %%P IN (%*) DO (
call :processParam %%P
)
goto:End
:processParam [%1 - param]
#echo "processparam : %1"
FOR /F "tokens=1,2 delims=:" %%G IN ("%1") DO (
#echo a,b %%G %%H
set nameWithSlash=%%G
set name=!nameWithSlash:~1!
#echo n=!name!
set value=%%H
set !name!=!value!
)
goto :eof
:End
Simple example of batch code using %var%, !var!, and %%.
In this example code, focus here is that we want to capture a start time using the built in variable TIME (using time because it always changes automatically):
Code:
#echo off
setlocal enabledelayedexpansion
SET "SERVICES_LIST=MMS ARSM MMS2"
SET START=%TIME%
SET "LAST_SERVICE="
for %%A in (%SERVICES_LIST%) do (
SET START=!TIME!
CALL :SOME_FUNCTION %%A
SET "LAST_SERVICE=%%A"
ping -n 5 127.0.0.1 > NUL
SET OTHER=!START!
if !OTHER! EQU !START! (
echo !OTHER! is equal to !START! as expected
) ELSE (
echo NOTHING
)
)
ECHO Last service run was %LAST_SERVICE%
:: Function declared like this
:SOME_FUNCTION
echo Running: %1
EXIT /B 0
Comments on code:
Use enabledelayedexpansion
The first three SET lines are typical
uses of the SET command, use this most of the time.
The next line is a for loop, must use %%A for iteration, then %%B if a loop inside it
etc.. You can not use long variable names.
To access a changed variable such as the time variable, you must use !! or set with !! (have enableddelayexpansion enabled).
When looping in for loop each iteration is accessed as the %%A variable.
The code in the for loop is point out the various ways to set a variable. Looking at 'SET OTHER=!START!', if you were to change to SET OTHER=%START% you will see why !! is needed. (hint: you will see NOTHING) output.
In short !! is more likely needed inside of loops, %var% in general, %% always a for loop.
Further reading
Use the following links to determine why in more detail:
Difference between %variable% and !variable! in batch file
Variable usage in batch file
To expand on the answer I came here to get a better understanding so I wrote this that can explain it and helped me too.
It has the setlocal DisableDelayedExpansion in there so you can locally set this as you wish between the setlocal EnableDelayedExpansion and it.
#echo off
title %~nx0
for /f "tokens=*" %%A in ("Some Thing") do (
setlocal EnableDelayedExpansion
set z=%%A
echo !z! Echoing the assigned variable in setlocal scope.
echo %%A Echoing the variable in local scope.
setlocal DisableDelayedExpansion
echo !z! &rem !z! Neither of these now work, which makes sense.
echo %z% &rem ECHO is off. Neither of these now work, which makes sense.
echo %%A Echoing the variable in its local scope, will always work.
)
set list = a1-2019 a3-2018 a4-2017
setlocal enabledelayedexpansion
set backup=
set bb1=
for /d %%d in (%list%) do (
set td=%%d
set x=!td!
set y=!td!
set y=!y:~-4!
if !y! gtr !bb1! (
set bb1=!y!
set backup=!x!
)
)
rem: backup will be 2019
echo %backup%
Try this:
setlocal EnableDelayedExpansion
...
for /F "tokens=*" %%a in ('type %FileName%') do (
set z=%%a
echo !z!
echo %%a
)
You can use a macro if you access a variable outside the scope
#echo off
::Define macro
set "sset=set"
for /l %%a in (1,1,4) do (
::set in loop
%sset% /a "x[%%a]=%%a*%%a"
if %%a equ 4 (
:: set in condition
%sset% "x[%%a]=x Condition"
%sset% "y=y Condition"
)
)
echo x1=%x[1]% x2=%x[2]% x3=%x[3]% x4=%x[4]% y=%y%
:: Bonus. enableDelayedExpansion used to access massive from the loop
setlocal enableDelayedExpansion
echo Echo from the loop
for /l %%a in (1,1,4) do (
::echo in one line - echo|set /p =
echo|set /p "=x%%a=!x[%%a]! "
if %%a equ 4 echo y=%y%
)
pause
I know this isn't what's asked but I benefited from this method, when trying to set a variable within a "loop". Uses an array. Alternative implementation option.
SETLOCAL ENABLEDELAYEDEXPANSION
...
set Services[0]=SERVICE1
set Services[1]=SERVICE2
set Services[2]=SERVICE3
set "i=0"
:ServicesLoop
if defined Services[%i%] (
set SERVICE=!Services[%i%]!
echo CurrentService: !SERVICE!
set /a "i+=1"
GOTO :ServicesLoop
)
The following should work:
setlocal EnableDelayedExpansion
for /F "tokens=*" %%a in ('type %FileName%') do (
set "z=%%a"
echo %z%
echo %%a
)

getting filename in variable & echoing them

In a directory I want to get each filename into a variable and then echo the variable to the screen.
REM Example 1 works but does not put filename in variable
FOR %%F in (*.*) do (
echo %%F
)
REM Example 2 here I try to put the filename into a variable named x but when I run it it only displays the filename of
FOR %%F in (*.*) do (
set x=%%F
echo %x%
)
How can I fix this?
I think you should use delayed expansion like so
#echo off
setlocal EnableDelayedExpansion
FOR %%F in (*.*) do ( set x=%%F & echo !x! )

Trouble getting a moving script to read filename and perform actions based on this

I am trying to get a mover batch script to read the filenames in a folder and do things to them based on the filename before moving them.
I have no trouble getting the files to be moved but I can't get the doing stuff based on filename part right.
#ECHO on
setlocal enableDelayedExpansion
SET src_folder=c:\recordz
SET tar_folder=\\TOWER\Temprec
:LOOP
for /f "delims=" %%a IN ('dir "%src_folder%"\*.mpg /b') do (
set "var=%%~na"
Echo %var%
Rem this part is supposed to check if NFL is part of the filename
If NOT "%var%"=="%var:NFL=%" (
echo Found inside
REN "%src_folder%\%%~na.mpg" "%%~na.ts"
move %src_folder%\"%%~na.ts" %tar_folder%
) else (
echo No cigar
move %src_folder%\"%%~na.mpg" %tar_folder%
)
)
REM Crafty 5 minute delay...
PING 1.1.1.1 -n 1 -w 1800000 >NUL
GOTO LOOP
When I run the above, I get this:
C:\Scripts>(
set "var=Feux_20161003_21002200"
Echo
If NOT "" == "NFL=" (
echo Found inside
REN "c:\recordz\Feux_20161003_21002200.mpg" "Feux_20161003_21002200.ts"
move c:\recordz\"Feux_20161003_21002200.ts" \\TOWER\Temprec
) else (
echo No cigar
move c:\recordz\"Feux_20161003_21002200.mpg" \\TOWER\Temprec
)
)
ECHO is on.
Found inside
Although you have enabled the delayed expansion you are not using it. Change % to ! inside the loop.
for /f "delims=" %%a IN ('dir "%src_folder%"\*.mpg /b') do (
set var=%%~na
Echo !var!
Rem this part is supposed to check if NFL is part of the filename
If NOT "!var!"=="!var:NFL=!" (
echo Found inside
REN "%src_folder%\%%~na.mpg" "%%~na.ts"
move %src_folder%\"%%~na.ts" %tar_folder%
) else (
echo No cigar
move %src_folder%\"%%~na.mpg" %tar_folder%
)
)

How to assign call argument to var and echo it in Windows batch script

I want to do this:
set kommune
FOR /F "tokens=* delims=" %%x in (DBLib.txt) DO (
CALL :decryptLine "%%x"
)
GOTO:eof
:decryptLine
for /f "tokens=1,* delims==" %%a in ("%~1") do set argument=%%a & set value=%%b
set "argument=%argument:~0,-2%"
set "value=%value:~1%"
call:updateVar "%argument%" "%value%"
GOTO:EOF
:updateVar
IF "%~1" == "KommuneNavn" (
ECHO "%~2"
ECHO "KommuneNavn"
set kommune=%~2
ECHO kommune = "%kommune%" testhest
)
What it outputs:
"ABC Test Kommune"
"KommuneNavn"
"kommune = "" testhest"
How do i copy the value of the secont argument to the Variable "kommune"? And Echo it?
Edit 1: updated to exact code. "inside IF"
#ECHO OFF
SETLOCAL
set kommune
FOR /F "tokens=* delims=" %%x in (q27922463.txt) DO (
CALL :decryptLine "%%x"
)
GOTO:eof
:decryptLine
for /f "tokens=1,* delims==" %%a in ("%~1") do set "argument=%%a" & set "value=%%b"
set "argument=%argument:~0,-2%"
set "value=%value:~1%"
call:updateVar "%argument%" "%value%"
GOTO:EOF
:updateVar
IF "%~1" == "KommuneNavn" (
ECHO "%~2"
ECHO "KommuneNavn"
set kommune=%~2
CALL ECHO kommune = "%%kommune%%" testhest
)
GOTO :eof
Critical point: You haven't shown us the content of your file, so we have to construct it: and I've changed the filename to suit my system (q27922463.txt)
contents of q27922463.txt
KommuneNavnxy=yourvalue
output generated:
"ourvalue"
"KommuneNavn"
kommune = "ourvalue" testhest
Note the positioning of the quotes in the set assignments. Batch is sensitive to spaces in a SET statement. SET FLAG = N sets a variable named "FLAGSpace" to a value of "SpaceN"
So, %%a becomes KommuneNavnxy, is assigned to argument, and the last 2 characters are removed, making KommuneNavn
Similarly, %%b gets yourvalue, you remove the first and make ourvalue
Since the string kommune is set within the code block of the if statement, you need to use call echo %%var%% to display it (one of several ways).

Errorlevel of command executed by batch for loop

The following code always displays 0 as the errorlevel, but when the copy command is done outside of the for loop command it returns a non zero errorlevel.
for /f "usebackq delims=" %%x in (`copy x y`) do (
set VAR=%%x
)
ECHO Errorlevel = %ERRORLEVEL%
ECHO VAR = %VAR%
Is is possible to get the errorlevel of the copy command executed by the for loop?
it works for me ! You only need to put the error checking within the DO parentheses
with a text file containing the copy commands (7200 lines; for example:
copy 2_97691_Scan.pdf O:\Data\Dev\Mins\PDFScan2\2011\4\2_97691_Scan.pdf),
I can run the following batch file
#echo off
setlocal EnableDelayedExpansion
for /F "delims=" %%I in (CopyCurrentPDFs.txt) do (
%%I
if !errorlevel! NEQ 0 echo %%I>>errorcopy.txt
)
I am assuming that you are copying files from one directory to another? If so, you could do something like this instead:
#echo off
setlocal EnableDelayedExpansion
set ERR=0
for %%x in (x) do (
copy %%x y
set ERR=!errorlevel!
set VAR=%%x
)
ECHO Errorlevel = %ERR%
ECHO VAR = %VAR%
The delayed expansion is required to get the actual value of errorlevel inside the loop instead of the value before the loop is entered.
If that isn't what you are trying to do, please clarify your objective.

Resources