I want to make the batch file that checking the account information.
Within below codes, I need 2,3,4 line from "net accounts" command outputs, and each line needs the individual process.
For to do this, I use the 'cnt' variable, and increase to checking.
However, 'cnt' doesn't increase at #1.
Why this happened, and how to solve it?
#echo off
SETLOCAL EnableDelayedExpansion
net accounts > accountInfo.txt
set cnt=0
echo """"""""""""""""""""""""""
for /f "tokens=1* delims=:" %%G in (accountInfo.txt) do (
ECHO.%%G | FIND /I "mum">Nul && (
SET var=%%~nH
Set myvar=!var!
set myvar=!myvar: =!
echo %%G !myvar!
echo %cnt%
set /A cnt+=1 ---------- here! #1
) || ( ECHO. )
)
echo """"""""""""""""""""""""""
ENDLOCAL
pause
You are using DelayedExpansion everywhere else in your code. Why not there as well?
Just change echo %cnt% to echo !cnt! and you should be fine.
Reason for that is that in batch blocks of code beeing surrounded by parenthesis are calculated at once. To see the updated value use DelayedExpansion as said above.
Related
All the P(numbers) are paths. For example, %P1% might be D:\ . Then, I get them to say a number. If they choose 1, I combine that with a P. That gives P1, the first variable. Can I set A to the variable P1? It would make the code way more optimized. I want to try and fit everything in a ridiculously tiny amount of space.
Download: https://mega.nz/file/QYZA3RbQ#Uvr9acXEBssYdXSHkdas1OjFt0X6xdmyl1WLH9HbmP8
echo 1. %P1%
echo 2. %P2%
echo 3. %P3%
echo 4. %P4%
echo 5. %P5%
set /p Pc=
set "a=p%pc%"
echo %a%
pause```
Short answer, based on the initial code:
Using delayedexpansion
set "a=!P%Pc%!"
echo %a%
or use call
call set "a=%%P%Pc%%%"
echo %a%
However. to do this right, You will need to change the way your config file works.
For now, your config has a major flaw, you explicitly want to ignore certain line numbers, which if someone removes or add a line, it will break your code. You need to use some for loops and then skip lines that starts with REM
So the config needs to look something like this (I made it smaller for the sake of a shorter answer):
REM Please set this to 1, or the program will NOT run!
1
REM ------------------------------------------------------------------------------------------
REM Please put paths to the folder your [PWADS] are in. Not the pwads themselves.
REM ------------------------------------------------------------------------------------------
pwads=C:\Some path
pwads=D:\Another
REM ------------------------------------------------------------------------------------------
REM Please put the path to your [IWADS]. Only ten though! Make sure it's the iwads themselves.
REM ------------------------------------------------------------------------------------------
iwads=D:\iwads1
iwads=D:\some path2
REM ------------------------------------------------------------------------------------------
REM Please put the path to your [Source Port] exe's. You must be doing something weird if you have more than ten.
REM ------------------------------------------------------------------------------------------
sp=D:\
sp=E:\
REM ------------------------------------------------------------------------------------------
REM Now, please leave this alone. It's so I know everything works.
REM ------------------------------------------------------------------------------------------
1
Now the code. portion.
#echo off
setlocal enabledelayedexpansion
set pwnum=0
set iwnum=0
set spnum=0
for /f "tokens=1,* delims==" %%i in ('type launcherconfiguration.txt ^| findstr /v "REM "') do (
if "%%i" equ "0" (
echo not configured
goto :eof
)
if "%%~i" == "pwads" (
set /a pwnum+=1
set "PWADlocat!pwnum!=%%~j"
) else (
if "%%~i" == "iwads" (
set /a iwnum+=1
set "IWADlocat!iwnum!=%%~j"
) else (
if "%%~i" == "sp" (
set /a spnum+=1
set "SPlocat!spnum!=%%~j"
)
)
)
)
echo PWADLocation:
for /l %%a in (1,1,%pwnum%) do echo %%a. !PWADLocat%%a!
set /p pw=Choose:
call echo you chose %%PWADlocat!pw!%%
call set "PW=%%PWADlocat!sp!%%"
echo you chose %PW%
pushd "%PW%" rem This will goto the dir
rem do other things
popd
echo IWADLocation:
for /l %%a in (1,1,%iwnum%) do echo %%a. !IWADLocat%%a!
set /p pw=Choose:
call set "IW=%%IWADlocat!sp!%%"
echo you chose %IW%
pushd "%IW%" rem This will goto chosen the dir
rem do other things
popd
echo SPLocation:
for /l %%a in (1,1,%spnum%) do echo %%a. !SPLocat%%a!
set /p sp=Choose:
call set "SP=%%SPlocat!sp!%%"
echo you chose %SP%
pushd "%SP%" rem This will goto the chosen SP dir
rem do other things
popd
So let me explain it briefly. We set a number per datatype, we simply increase the count as more lines matched are found and then we use another for /l loop to just use the count again.
To test this, you need to copy this code into a new batch file, place it in the same location as your config file and test it. There are alot more to your code, but I have only focused on what you asked.
Note, I would still prefer to use choice but because of the beeping you mentioned, I retained the set /p option in this code.
I'm trying to get a test code working so I can make a more complex version of the script for my actual needs, but I'm struggling with the FIND command.
My code:
#echo off
SETLOCAL DISABLEDELAYEDEXPANSION
>"%~dpn1_b.txt" (
FOR /F "tokens=1* delims=]" %%j in ('find /V /N "" %1') DO (
SET "currentLine=%%k"
SETLOCAL ENABLEDELAYEDEXPANSION
IF "!currentLine:~0,3!"=="12/" (
SET string=!currentLine:~0,2!!currentLine:~3,4!
FIND "%string%" 111.txt > nul
IF %errorlevel% EQU 0 (SET "currentLine=!currentLine:~0,2!!currentLine:~3!")
)
ECHO(!currentline!
ENDLOCAL
)
)
This is executed by dragging test.txt onto the batch file.
111.txt holds 123456. test.txt has 12/3456 on the first line and 12/4456 on the second line. The script is supposed to remove the slash from the first line but not from the second. Any idea what went wrong?
Within the FOR loop body, all environment variable expansions using the %var% format will be pre-expanded. You still need to use the delayed expansion !var! format even for internal variables like errorlevel.
FOR /F ... (
...
FIND "!string!" 111.txt > nul
IF !errorlevel! EQU 0 (SET "currentLine=!currentLine:~0,2!!currentLine:~3!")
)
As Ryan mentioned, this is clearer if you leave ECHO enabled as you see that with the original code the last two statements in the loop were being pre-expanded:
FIND "" 111.txt 1>nul
IF 0 EQU 0 (SET "currentLine=!currentLine:~0,2!!currentLine:~3!" )
interesting: you get the line numbers (%%j) but then don't use it...
How about:
...
if "%%j"=="[1" (
...
) else (
echo %%k
)
...
I'm 90% of the way there on a Windows Batch file.
It takes 2 input parameters, input and output files.
It then reads in the input file, and substrings certain lines into arrays (Well line 2 onwards).
Then we come to a loop for outputting.
With delayed expansion on my counter for going through the array doesn't update unless I use !counter2!, %counter2% doesn't work.
Using !arrayname[!counter2!]! doesn't work.
Here is the code as it stands.
#Echo off
if [%1] == [] goto usage
if [%2] == [] goto usage
echo start time : %time%>logfile.log
set input_file=%1
set output_file=%2
if exist %output_file% del %output_file%
Echo Start reading %input_file%>> logfile.log
setLocal EnableDelayedExpansion
set /a counter=1
for /F "tokens=* delims=" %%a in ('type %input_file%') DO (
::echo !counter!
if "!counter!"=="1" set header=%%a
if not "!counter!"=="1" (
set data[!counter!]=%%a
set line=%%a
set jobnumber[!counter!]=!line:~0,7!
set docnumber[!counter!]=!line:~7,5!
set pagecount[!counter!]=!line:~12,2!
set customernumber[!counter!]=!line:~14,20!
set presort[!counter!]=0000
set postcode[!counter!]=0000
set inserts[!counter!]=!line:~36,11!
set filler[!counter!]=000000
set address[!counter!]=!line:~58,350!
set filler2[!counter!]=" "
set endline[!counter!]=X
)
set /a counter=counter+1
)
Echo Start writing %output_file%>> logfile.log
for /L %%G in (2,1,%counter%) DO (
set counter2=%%G
echo !counter2!
echo !jobnumber[%counter2%]!!docnumber[%counter2%]!!pagecount[%counter2%]!!customernumber[%counter2%]!!presort[%counter2%]!!postcode[%counter2%]!!inserts[%counter2%]!!filler[%counter2%]!!address[%counter2%]!!filler2[%counter2%]!!endline[%counter2%]!>>%output_file%
)
echo end time : %time%>>logfile.log
pause
goto :eof
:usage
echo Usage: blah.bat input_filename output_filename
pause
goto :eof
It is the echo !jobnumber[%counter2%]! where things are not being resolved.
The echo !counter2! works fine.
Before you ask, Yes I know this could be done better and easier in C# or another programming language, However I am tasked with doing it in a windows batch file.
Thanks in advance for any help provided.
Tel
Try with:
for /L %%G in (2,1,%counter%) DO (
set counter2=%%G
echo !counter2!
echo !jobnumber[%%G]!!docnumber[%%G]!!pagecount[%%G]!!customernumber[%%G]!!presort[%%G]!!postcode[%%G]!!inserts[%%G]!!filler[%%G]!!address[%%G]!!filler2[%%G]!!endline[%%G]!>>%output_file%
)
You are not changing the value of the coutner2 so you don't need it and you can directly use %%G.
Though if you need changes in counter2 you'll have to wrap it again in for loop and to use its tokens.
So the situation is like so... I have two nested if statements and then a loop inside them (using the GoTo command and an incremented variable - for loop simulation :D). As you probably know to assign new values to variables inside of parentheses (of an if statement) you have to use delayedexpansion. Also to use variables in the for command you have to double the percent marks like so %%. I want to set the tokens in a for /f command to be the value of the variables I'd like. The problem is doubling the exclamation marks has no effect. I also tried all sorts ... like using quotes, escaping those quotes, using quote alternatives, but it was all to no avail. If you can help in any way that would be just great, because I can't think of anything at all :(. Thank you in advance guys!
If that made no sense here's the code:
#echo off
set FilePath=test.bat
set RefreshRate=3
setlocal enabledelayedexpansion enableextensions
:GetData
if defined FilePath (
if exist "%FilePath%" (
:GetLines
cls
:: This is how I find out how many lines there is in the file
set "cmd=findstr /R /N "^^" "%FilePath%" | find /C ":""
for /f %%a in ('!cmd!') do set Lines=%%a
:ShowCode
cls
set LineNum+=1
if ""!LineNum!"" GTR ""!Lines!"" GoTo Refresh
::THIS IS THE MAIN PROBLEM
for /f "tokens=%%LineNum%% delims=$" %%b in ("%FilePath%") do (
set Line%LineNum%=%%b
echo !LineNum!. | !Line%LineNum%!
GoTo ShowCode
)
)
)
:Refresh
ping localhost -n %RefreshRate% >nul
GoTo GetData
I'm sorry that I didn't have enough time to make it more readable, but it should make the whole thing a little clearer.
First: do not use neither :: remark comments nor :label in a code block enclosed in () parentheses. A proof of harmfulness you could find in the labels.bat script encoded in output from a script provided thereinafter; an explanation here: Comments within bracketed code blocks.
In next script, non-empty lines of a particular plain text file (cf. set "FilePath=labels.bat") are saved to a pseudo-array LineAAA, where index AAA = line number. I do not know whether it isn't off topic according to your question but could give some useful clue...
#echo off
setlocal enabledelayedexpansion enableextensions
cls
set line
set "FilePath=labels.bat"
set /A "RefreshRate=3"
:GetData
if not defined FilePath (
echo %%FilePath%% not defined
goto :eof
)
if not exist "%FilePath%" (
echo %FilePath% does not exist
goto :eof
rem following 'else' (sub)statement seems to be superabundant
) else (
rem GetLines
rem This is how I find out how many lines there is in the file
set "cmd=findstr /R /N "^^" "%FilePath%" | find /C ":""
for /f %%a in ('!cmd!') do set /A "Lines=%%a"
set /A "LineNum=0"
set "Line000=#rem %FilePath%"
for /f "tokens=*" %%b in (%FilePath%) do (
set /A "LineNum+=1"
set "LineX=000000000!LineNum!"
set "LineX=!LineX:~-3!"
set "Line!LineX!=%%b"
)
call :Refresh
)
set line
rem pause
endlocal
goto :eof
:Refresh
ping localhost -n %RefreshRate% | findstr /I "Packets: statistics"
rem >nul
GoTo :eof
Output:
Environment variable line not defined
Ping statistics for ::1:
Packets: Sent = 3, Received = 3, Lost = 0 (0% loss),
Line000=#rem labels.bat
Line001=#SETLOCAL enableextensions enabledelayedexpansion
Line002=#ECHO ON >NUL
Line003=if ""=="" (
Line004=rem comment
Line005=#echo rem comment
Line006=)
Line007=if ""=="" (
Line008=:: comment
Line009=#echo :: comment
Line010=)
Line011=if ""=="" (
Line012=:label
Line013=#echo :label
Line014=)
Line015=#ENDLOCAL
Line016=#goto :eof
LineNum=16
Lines=16
LineX=016
labels.bat output:
d:\bat>labels.bat
d:\bat>if "" == "" (
rem comment
)
rem comment
d:\bat>if "" == "" (#echo :: comment )
'#echo' is not recognized as an internal or external command,
operable program or batch file.
d:\bat>if "" == "" (#echo :label )
'#echo' is not recognized as an internal or external command,
operable program or batch file.
d:\bat>
Tokens property don't go in the brackets they go in quotes and are wrong anyway. It's the nth to nth delimited term.
Type
for /?
for examples
I am trying to read the filename and according to the filename set the Output variable.
I have tried using findstr directly on %%F (findstr /i "M002" %%F >nul 2>&1 ) and also writing to a temp text file (as below) to test and read it, but nothing worked.
What I'm doing wrong?
P.S. If I remove this out from the loop the code works, but I need it within the loop due to the last line.
rem ===========================================
set FileType=pdf
for %%F in (%~dp0*.%FileType%) do (
rem ECHO %%F
echo "%%F" > test.txt
findstr /i "M002" test.txt >nul 2>&1
echo %errorlevel%
if not %errorlevel% == 0 (
echo "4pp"
echo %%F
set Output=4PP
) ELSE (
echo "Letter"
echo %%F
set Output=Letter
)
set NetComm="XYZ" "%Output%" etc etc etc
)
rem ====================================
Generation 5,961 of delayedexpansion.
Batch parses the entire statement from the for through to the last closing parenthesis and replaces any %var% with the value of that variable at the time the statement is parsed.
Consequently, attempting to use a value which is established within the loop will fail. This applies to %output% and %errorlevel% in the current instance.
Dealing with %errorlevel% is easy. The syntax
if errorlevel n
works on the run-time value of errorlevel and is true if errorlevel has been set to n or greater than n.
Personally, I find the if not condition ... else clumsy. I can't see why it's so common. Fuzzy thinking in my book...
There are three common ways to overcome the problem, each has its own advantages and disadvantages, proponents and critics.
First, the "documented" method. Use a setlocal enabledelayedexpansion instruction. Once this instruction has been executed, !var! will access the current value and %var% the initialvalue ofvar`.
Second, the subroutine method. CALL :sub within a loop executes a subroutine (see the documentation - call /? from the prompt) and within that subroutine, %var% will have the value as established within the loop.
Third, it's sometimes possible to use call echo %%var%% (or call someotherinsruction) where the call is executiong the target as if it was a subroutine.
Hence, in your case, a fix might be
rem ===========================================
set FileType=pdf
for %%F in (%~dp0*.%FileType%) do (
rem ECHO %%F
findstr /i "M002" "%%F" >nul 2>nul
CALL echo %%errorlevel%%
if errorlevel 1 (
echo "4pp"
echo %%F
set Output=4PP
) ELSE (
echo "Letter"
echo %%F
set Output=Letter
)
CALL set NetComm="XYZ" "%%Output%%" etc etc etc
)
rem ====================================
depending entirely on your definition of "works" (which is not an absolute - it has meaning only to you.)