Batch - Findstr - Escape chars - batch-file

I have a textfile/logfile called textexample.txt with a lot of lines which was generated from a 3rd Party Software and therefore does contain a lot of special characters.
Now im searching for some special keywords in this logfile and therefore i use findstr.
The problem is that i want to store every character which has to be escaped in a variable called charsToEscape, but this is not working proper. Is there any 'simple' solution for my example?
Here is the textfile "textexample.txt" im searching in:
17:09:47| | |OS ver : 1.2 AB:0.0 CD:1234 KType:-1
17:09:48| |InitInstance() |Start copy files from Section=Files
17:09:49| | | ******************************
17:09:50| |StartExe |Here is the Value (1234) i am searching"
17:09:50| |StartExe |your path="C:\Some\Specific\Path"
17:09:50| |someRandomWords |WaitLevel="1" (default value)
Here is my Batchfile:
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
:MAIN
setlocal
::REM List with the expected Values im searching for..
set "expected_value_pool=9876 turn 1234 failure adios"
call :SearchValue "%expected_value_pool%" "readback_value"
if "!errorlevel!" equ "0" (
echo readback=!readback_value!
)
pause
exit /b 0
REM Function, which checks if the give return value is in a specific textfile (line for line check)
:SearchValue
setlocal
set "_expected_value_pool=%~1"
set "_readback_value=%~2"
set "file=textexample.txt"
set "charsToEscape=/ \ > < ? | " - $ ( ) [ ] { } : = ."
set "escapeChar=^"
for /f "tokens=*" %%a in (%file%) do (
set "act_line=%%a"
for %%c in (%charsToEscape%) do (
set "act_line=!act_line:%%c=%escapeChar%%%c!"
)
for %%i in (%_expected_value_pool%) do (
echo !act_line!|findstr /r "^.*%%i.*$" >NUL
if "!errorlevel!" equ "0" (
(endlocal
if "%_readback_value%" neq "" (set "%_readback_value%=%%i")
)
exit /b 0
)
)
)
exit /b 1
UPDATE:
i get the error ">" cant be processed syntactically at this point from the line set "charsToEscape=/ \ > < ? | " - $ ( ) [ ] { } : = ." due to the special characters which cannot be proper processed

Related

Batch file: Where is the phantom line break coming from in this code?

I am trying to append a backslash to the end of a string (a folder name), and instead of getting a backslash, I seem to be getting a line break, 13 spaces, then finally the backslash. Where is this coming from?
Here is the code I wrote:
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
:: After the user chooses a folder from a menu, the choice is stored in ChosenFolder
:: A typical value for ChosenFolder would be "3 .\Folder1"
set "ParentFolder=!ChosenFolder:~2!^\"
echo ParentFolder is !ParentFolder!
The output I get is:
ParentFolder is .\Folder1
\
If I just manually set the ChosenFolder variable to "3 .\Folder", this error doesn't happen, so here is the code that ultimately generates the faulty value of ChosenFolder (a slightly modified version of Magoo's code that answered this question, bless his heart!)
SET "choicenames=z0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxy"
:: remove variables starting #
FOR /F "delims==" %%e In ('set # 2^>Nul') DO SET "%%e="
FOR /L %%e IN (1,1,%pagewidth%) DO SET "#spaces=!#spaces! "
:: Read dirnames to #nn, count to #entries
FOR /d %%e IN ("%~1\*.") DO SET /a #entries+=1&SET "#!#entries!=%%e"
SET /a #entries+=1&SET "#!#entries!=z Quit."
SET /a #columns=(#entries + pagesize - 1) / pagesize
SET /a #rows=(#entries + #columns - 1)/#columns
SET /a #columnwidth=(pagewidth/#columns) - 3
SET "#choices=z"
FOR /L %%e IN (1,1,%#entries%) DO (
rem column contents - max length + terminal spaces
IF %%e neq %#entries% (
SET "#%%e=!#%%e:~-%#columnwidth%!%#spaces%"
SET "#%%e=!choicenames:~%%e,1! !#%%e:~0,%#columnwidth%!"
SET "#choices=!#choices!!choicenames:~%%e,1!"
)
)
FOR /L %%e IN (1,1,%#rows%) DO (
SET /a cols=%%e + %#rows%
SET /a #line=%%e + (%#rows% * 2^)
SET "cols=!cols! !#line!"
SET "#line=!#%%e!"
FOR %%y IN (!cols!) DO IF DEFINED #%%y SET "#line=!#line! !#%%y!"
ECHO !#line!
)
IF %#entries% gtr 36 (
choice /cs /c %#choices%
) ELSE (
choice /c %#choices%
)
IF ERRORLEVEL 2 (
ECHO ERRORLEVEL is %ERRORLEVEL%
SET /a #choices=%ERRORLEVEL%-1
CALL SET "ChosenFolder=%%#!#choices!%%"
ECHO choice made : !ChosenFolder:~2!
CHOICE /C snc /N /M "(S)elect, (N)avigate or (C)ancel? "
IF errorlevel 3 goto begin
IF errorlevel 2 CALL :SelectFolder !ChosenFolder:~2!
IF errorlevel 1 EXIT /B 0
) ELSE GOTO begin
#? contains the name as, eg : 3 u:\Folder1 . The spaces are added to lay out the menu appropriately, so they would need to be deleted (hence the series of spaces when manipulated and the need to lop off the leading 2 characters).
\ does not need to be escaped if simply appended to the string.
Note however - Use set "var=value" for setting string values - this avoids problems caused by trailing spaces. Don't assign " or a terminal backslash or Space. Build pathnames from the elements - counterintuitively, it is likely to make the process easier. If the syntax set var="value" is used, then the quotes become part of the value assigned.
FOR /d %%e IN ("%~1\*.") DO SET /a #entries+=1&SET "#!#entries!=%%e"&SET "#originalnames!#entries!=%%e"
To establish a parallel list of names, #originalnames?.
IF ERRORLEVEL 2 (
ECHO ERRORLEVEL is %ERRORLEVEL%
SET /a #choices=%ERRORLEVEL%-1
CALL SET "ChosenFolder=%%#originalnames!#choices!%%"
ECHO choice made : !ChosenFolder!
CHOICE /C snc /N /M "(S)elect, (N)avigate or (C)ancel? "
IF errorlevel 3 goto begin
IF errorlevel 2 CALL :SelectFolder
rem IF errorlevel 1 EXIT /B 0
) ELSE GOTO begin
GOTO :EOF
:selectfolder
ECHO +%chosenfolder%+
FOR /f "delims=" %%e in ("%chosenfolder%") do SET "Parentfolder=%%~dpe"
echo ParentFolder of %chosenfolder% is +%ParentFolder%+
GOTO :eof
(Note + on either end of the names to show absence of spaces.)
This assigns the original name (not the displayed name which may have been truncated) to chosenfolder.
Since chosenfolder is not within (...) (ie. a code block) you can use %chosenfolder% to access its contents. !chosenfolder! will also work, but it implies that the value of chosenfolder may vary because it's within a code block - but within the subroutine :SelectFolder there are no code blocks.
chosenfolder is of the form u:\folder 1. so the for assigns this to %%e and the parser then interprets u:\folder 1 as drive=u:, path=\ and filename=folder 1

Verifying MD5 hashes in Batch?

I am writing a batch file and I need it to verify a file's MD5 hash before continuing on with the script. For example:
#echo off
if MD5 equ 79054025255fb1a26e4bc422aef54eb4 (
echo MD5 identical!
) else (
echo MD5 does not match.
)
Thanks!
The standard Windows utility CERTUTIL can be used to generate MD5 (and other) hashes.
For example:
certutil -hashfile yourFile MD5
However, the output (versions prior to Windows 10) will not be formatted as a single string of contiguous hex digits.
npocmaka used CERTUTIL in his batch utility to generate a single MD5 string.
In a similar manner, I also used CERTUTIL with my utility: HASHSUM.BAT - a batch file emulation of unix utilities like md5sum, shasum, etc.
HASHSUM.BAT does more than compute MD5 for a single file, but it is also convenient to use for what you want.
For example:
echo 79054025255fb1a26e4bc422aef54eb4 yourFileName | hashsum /c /ns
REM - There must be exactly two spaces between the MD5 hash and the filename
Will yield output like
---------- <stdin> ----------
OK: yourFileName
or
---------- <stdin> ----------
*FAILED: yourFileName
Or you can take total control of the output
echo 79054025255fb1a26e4bc422aef54eb4 yourFileName | hashsum /c /q && (
echo MD5 identical!
) || (
echo MD5 does not match.
)
Or, if you really wanted, you could capture the MD5 value and do the comparison yourself:
for /f %%N in ('hashsum /a md5 yourFileName') do set "MD5=%%N"
if %MD5% equ 79054025255fb1a26e4bc422aef54eb4 (
echo MD5 identical!
) else (
echo MD5 does not match.
)
I'm posting the code for the current version 1.4 of HASHSUM.BAT, but I don't promise to keep this code up-to-date. I recommend you get the code from the DOSTIPS site where I originally posted it. There you can also see a more thorough discussion of all the HASHSUM.BAT capabilities, as well as some more examples of usage.
#if (#X)==(#Y) #end /* Harmless hybrid line that begins a JScript comment
#goto :Batch
::::HASHNUM.BAT history
::::
:::: v1.4 2016-12-26 - Convert /A value to upper case because some Windows
:::: versions are case sensitive. Also improve JScript file
:::: read performance by reading 1000000 bytes instead of 1.
:::: v1.3 2016-12-17 - Bug fixes: Eliminate unwanted \r\n from temp file by
:::: reading stdin with JScript instead of FINDSTR.
:::: Fix help to ignore history.
:::: v1.2 2016-12-07 - Bug fixes: Exclude FORFILES directories and
:::: correct setlocal/endlocal management in :getOptions
:::: v1.1 2016-12-06 - New /V option, and minor bug fixes.
:::: v1.0 2016-12-05 - Original release
:::
:::HASHSUM [/Option [Value]]... [File]...
:::
::: Print or check file hashes using any of the following standard
::: hash algorithms: MD5, SHA1, SHA256, SHA384, or SHA512.
:::
::: HASHSUM always does a binary read - \r\n is never converted to \n.
:::
::: In the absence of /C, HASHSUM computes the hash for each File, and writes
::: a manifest of the results. Each line of output consists of the hash value,
::: followed by a space and an asterisk, followed by the File name. The default
::: hash alogrithm is sha256. File may include wildcards, but must not contain
::: any path information.
:::
::: If File is not given, then read from standard input and write the hash
::: value only, without the trailing space, asterisk, or file name.
:::
::: Options:
:::
::: /? - Prints this help information to standard output.
:::
::: /?? - Prints paged help using MORE.
:::
::: /V - Prints the HASHNUM.BAT version.
:::
::: /A Algorithm
:::
::: Specifies one of the following hash algorithms:
::: MD5, SHA1, SHA256, SHA384, SHA512
:::
::: /P RootPath
:::
::: Specifies the root path for operations.
::: The default is the current directory.
:::
::: /S - Recurse into all Subdirectories. The relative path from the root
::: is included in the file name output.
::: This option is ignored if used with /C.
:::
::: /I - Include the RootPath in the file name output.
::: This option is ignored if used with /C.
:::
::: /T - Writes a space before each file name, rather than an
::: asterisk. However, files are still read in binary mode.
::: This option is ignored if used with /C.
:::
::: /C - Read hash values and file names from File (the manifest), and verify
::: that local files match. File may include path information with /C.
:::
::: If File is not given, then read hash and file names from standard
::: input. Each line of input must have a hash, followed by two spaces,
::: or a space and an asterisk, followed by a file name.
:::
::: If /A is not specified, then the algorithm is determined by the
::: File extension. If the extension is not a valid algorithm, then
::: the algorithm is derived based on the length of the first hash
::: within File.
:::
::: Returns ERRORLEVEL 1 if any manifest File is not found or is invalid,
::: or if any local file is missing or does not match the hash value in
::: the manifest. If all files are found and match, then returns 0.
:::
::: /NE - (No Errors) Suppresses error messages when using /C.
:::
::: /NM - (No Matches) Suppresses listing of matching files when using /C.
:::
::: /NS - (No Summary) Suppresses summary information when using /C.
:::
::: /Q - (Quiet) Suppresses all output when using /C.
:::
:::HASHSUM.BAT version 1.4 was written by Dave Benham
:::maintained at http://www.dostips.com/forum/viewtopic.php?f=3&t=7592
============= :Batch portion ===========
#echo off
setlocal disableDelayedExpansion
:: Define options
set "options= /A:"" /C: /I: /P:"" /S: /T: /?: /??: /NE: /NM: /NS: /Q: /V: "
:: Set default option values
for %%O in (%options%) do for /f "tokens=1,* delims=:" %%A in ("%%O") do set "%%A=%%~B"
set "/?="
:getOptions
if not "%~1"=="" (
set "test=%~1"
setlocal enableDelayedExpansion
if "!test:~0,1!" neq "/" endlocal & goto :endOptions
set "test=!options:*%~1:=! "
if "!test!"=="!options! " (
endlocal
>&2 echo Invalid option %~1
exit /b 1
) else if "!test:~0,1!"==" " (
endlocal
set "%~1=1"
) else (
endlocal
set "%~1=%~2"
shift /1
)
shift /1
goto :getOptions
)
:endOptions
:: Display paged help
if defined /?? (
(for /f "delims=: tokens=*" %%A in ('findstr "^:::[^:] ^:::$" "%~f0"') do #echo(%%A)|more /e
exit /b 0
) 2>nul
:: Display help
if defined /? (
for /f "delims=: tokens=*" %%A in ('findstr "^:::[^:] ^:::$" "%~f0"') do echo(%%A
exit /b 0
)
:: Display version
if defined /v (
for /f "delims=: tokens=*" %%A in ('findstr /ric:"^:::%~nx0 version" "%~f0"') do echo(%%A
exit /b 0
)
:: If no file specified, then read stdin and write to a temp file
set "tempFile="
if "%~1" equ "" set "tempFile=%~nx0.%time::=_%.%random%.tmp"
if defined tempFile cscript //nologo //E:JScript "%~f0" "%temp%\%tempFile%"
if defined /P cd /d "%/P%" || exit /b 1
if defined /C goto :check
:generate
if defined tempFile cd /d "%temp%"
if not defined /A set "/A=sha256"
if defined /S set "/S=/s"
if defined /T (set "/T= ") else set "/T=*"
call :defineEmpty
if not defined /P goto :generateLoop
if not defined /I goto :generateLoop
if "%/P:~-1%" equ "\" (set "/I=%/P:\=/%") else set "/I=%/P:\=/%/"
set "rtn=0"
:generateLoop
(
for /f "delims=" %%F in (
'forfiles %/s% /m "%tempFile%%~1" /c "cmd /c if #isdir==FALSE echo #relpath" 2^>nul'
) do for /f "delims=" %%A in (
'certutil.exe -hashfile %%F %/A% ^| find /v ":" ^|^| if %%~zF gtr 0 (echo X^) else echo %empty%'
) do (
set "file=%%~F"
set "hash=%%A"
setlocal enableDelayedExpansion
set "file=!file:~2!"
if defined tempFile (
if !hash! equ X (
set "rtn=1"
echo ERROR
) else echo !hash: =!
) else (
if !hash! equ X (
set "rtn=1"
echo ERROR: !/I!!file!
) else echo !hash: =! !/T!!/I!!file:\=/!
)
endlocal
)
) || (
set "rtn=1"
echo MISSING: %/T%%1
)
shift /1
if "%~1" neq "" goto :generateLoop
if defined tempFile del "%tempFile%"
exit /b %rtn%
:check
if defined /Q for %%V in (/NE /NM /NS) do set "%%V=1"
set /a manifestCnt=missingManifestCnt=invalidCnt=missingCnt=failCnt=okCnt=0
:checkLoop
set "alogorithm=%/A%"
if defined tempFile set "tempFile=%temp%\%tempFile%"
for %%F in ("%tempFile%%~1") do call :checkFile "%%~F"
if defined tempFile del "%tempFile%"
shift /1
if "%~1" neq "" goto :checkLoop
if not defined /NS (
echo ========== SUMMARY ==========
echo Total manifests = %manifestCnt%
echo Matched files = %okCnt%
echo(
if %missingManifestCnt% gtr 0 echo Missing manifests = %missingManifestCnt%
if %invalidCnt% gtr 0 echo Invalid manifests = %invalidCnt%
if %missingCnt% gtr 0 echo Missing files = %missingCnt%
if %failCnt% gtr 0 echo Failed files = %failCnt%
)
set /a "1/(missingManifestCnt+invalidCnt+missingCnt+failCnt)" 2>nul && (
echo(
exit /b 1
)
exit /b 0
:checkFile
set /a manifestCnt+=1
if not defined /Q if defined tempfile (echo ---------- ^<stdin^> ----------) else echo ---------- %1 ----------
if not defined algorithm set "/A="
set "src=%~1"
if not defined /A echo *.md5*.sha1*.sha256*.sha384*.sha512*|find /i "*%~x1*" >nul && for /f "delims=." %%A in ("%~x1") do set "/A=%%A"
findstr /virc:"^[0123456789abcdef][0123456789abcdef]* [ *][^ *?|<>]" %1 >nul 2>nul && (
if not defined /NE if defined tempFile (echo *INVALID: ^<stdin^>) else echo *INVALID: %1
set /a invalidCnt+=1
exit /b
)
(
for /f "usebackq tokens=1* delims=* " %%A in (%1) do (
set "hash0=%%A"
set "file=%%B"
if defined /A (call :defineEmpty) else call :determineFormat
setlocal enableDelayedExpansion
set "file=!file:/=\!"
for /f "tokens=1* delims=" %%C in (
'certutil.exe -hashfile "!file!" !/A! ^| find /v ":" ^|^| if exist "!file!" (echo !empty!^) else echo X'
) do set "hash=%%C"
if /i "!hash0!" equ "!hash: =!" (
if not defined /NM echo OK: !file!
endlocal
set /a okCnt+=1
) else if !hash! equ X (
if not defined /NE echo *MISSING: !file!
endlocal
set /a missingCnt+=1
) else (
if not defined /NE echo *FAILED: !file!
endlocal
set /a failCnt+=1
)
)
) 2>nul || (
if not defined /NE echo *MISSING: %1
set /a missingManifestCnt+=1
)
exit /b
:determineFormat
if "%hash0:~127%" neq "" (
set "/A=SHA512"
) else if "%hash0:~95%" neq "" (
set "/A=SHA384"
) else if "%hash0:~63%" neq "" (
set "/A=SHA256"
) else if "%hash0:~39%" neq "" (
set "/A=SHA1"
) else set "/A=MD5"
:defineEmpty
if /i "%/A%"=="md5" (
set "empty=d41d8cd98f00b204e9800998ecf8427e"
set "/A=MD5"
) else if /i "%/A%"=="sha1" (
set "empty=da39a3ee5e6b4b0d3255bfef95601890afd80709"
set "/A=SHA1"
) else if /i "%/A%"=="sha256" (
set "empty=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
set "/A=SHA256"
) else if /i "%/A%"=="sha384" (
set "empty=38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"
set "/A=SHA384"
) else if /i "%/A%"=="sha512" (
set "empty=cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"
set "/A=SHA512"
) else (
echo ERROR: Invalid /A algorithm>&2
(goto) 2>nul&exit /b 1
)
exit /b
************* JScript portion **********/
var fso = new ActiveXObject("Scripting.FileSystemObject");
var out = fso.OpenTextFile(WScript.Arguments(0),2,true);
var chr;
while( !WScript.StdIn.AtEndOfStream ) {
chr=WScript.StdIn.Read(1000000);
out.Write(chr);
}
try with MD5.BAT :
set "file=c:\myfile.ext"
call md5.bat "%file%" md5
if "%md5%" equ "79054025255fb1a26e4bc422aef54eb4" (
echo MD5 identical!
) else (
echo MD5 does not match.
)

Windows batch script ends unexpectedly

I am not familiar with windows batches.
I'm trying to write a script that will be included in a database migration script chain. It should check if SQL scripts have a hardcoded database name, and if it finds any, should warn the user, output file names, and stop the chain execution.
I reckon there are multiple problems with it..
set "lf=^"
setlocal EnableDelayedExpansion
for %%a in (functions sprocs up views) do (
cd %%a
for /f "tokens=*" %%b in ('findstr /lism "[MyDatabase]" *.sql') do (
if not [%%b] == [] (
call :append %%a\%%b
)
)
cd ..
)
if [%sinList%] == [] (
echo No hardcoded names in scripts found, continuing..
pause
) else (
echo Cannot continue database migration until you clear out hardcoded database name in files^%lf%%lf%
echo Files with hardcode^%lf%%lf% : %sinList%
pause
exit /b 1
)
goto :eof
:append
if defined sinList (
set sinList=%sinList%%1^%lf%%lf%
) else (
set sinList=%1^%lf%%lf%
)
goto :eof
Right now when I execute it I end up in /sprocs folder, doesn't output any results.
Turning on echo looks like this
C:\Portal\Database.Migration>dbname_hardcode_punisher.cmd
C:\Portal\Database.Migration>set "lf=^"
C:\Portal\Database.Migration>set "sinList="
C:\Portal\Database.Migration>setlocal EnableDelayedExpansion
C:\Portal\Database.Migration>for %a in (functions sprocs up views) do
( cd %a for /F "tokens=*" %b in ('findstr /lism "[MyDatabase]" .sql') do
(if not [%b] == [ ] (call :append %a\%b ) ) cd .. )
C:\Portal\Database.Migration>( cd functions for /F "tokens=" %b in
('findstr /lism "[MyDatabase]" .sql') do (if not [%b] == [ ] (call
:append functions\%b ) ) cd .. ) C:\Portal\Database.Migration>( cd
sprocs for /F "tokens=" %b in ('findstr /lism "[MyDatabase]" *.sql')
do (if not [%b] == [ ] (call :append sprocs\%b ) ) cd .. )
C:\Portal\Database.Migration\sprocs>(if not [Proc_name.sql] == []
(call :append sprocs\Another_proc.sql ) )
Also I'm afraid that if [%sinList%] == [] may not return the expected results since it could have one newline?
for the LineFeed trick to work, it needs delayed expansion (both with lf and the variable) and two empty lines:
setlocal enabledelayedexpansion
set lf=^
%= don't delete =%
%= these two lines =%
set new=hello!lf!world
echo !new!
echo Hello!lf!World
(Q:Where are the two required empty lines? A: %= anything =% is not defined and therefore gets parsed as nothing (empty). Just a reminder for the programmer not to delete them; You could also use just empty lines)

Split string in batch file

I am new to using batch files so could someone please help me split a string i am getting from a file.
I am using %USERPROFILE% to get my string.
The string is: "C:\Users\nicholas"
I would like to keep the C:\ part, but get rid of the \Users\nicholas part.
for /f "tokens=2 delims=\" %A in ('set userprofile') do echo %A\
See for /?
Also
echo %userprofile:~0,3%
If you carefully read the output of set /?, you'll find the answer:
May also specify substrings for an expansion.
%PATH:~10,5%
would expand the PATH environment variable, and then use only the 5
characters that begin at the 11th (offset 10) character of the expanded
result.
So, you can use something like this to get the first 3 characters of your string:
> echo %userprofile:~0,3%
C:\
I As you need the drive where where the users are located you can use directly
%systemdrive% variable - this is the drive where the windows is installed
II the easiest way to get a drive from path:
for %%a in ("%userprofile%") do echo %%~da\
%~da - expands a path to its drive only
III over-complicated but powerful way (split function that can be used for a different things):
#echo off
call :split "%userprofile%" "\" 1 drive
echo %drive%\
goto :eof
:split [%1 - string to be splitted;%2 - split by;%3 - possition to get; %4 - if defined will store the result in variable with same name]
::http://ss64.org/viewtopic.php?id=1687
setlocal EnableDelayedExpansion
set "string=%~2%~1"
set "splitter=%~2"
set /a position=%~3
set LF=^
rem ** Two empty lines are required
echo off
for %%L in ("!LF!") DO (
for /f "delims=" %%R in ("!splitter!") do (
set "var=!string:%%~R%%~R=%%~L!"
set "var=!var:%%~R=%%~L!"
if "!var!" EQU "!string!" (
echo "%~1" does not contain "!splitter!" >&2
exit /B 1
)
)
)
if "!var!" equ "" (
endlocal & if "%~4" NEQ "" ( set "%~4=")
)
if !position! LEQ 0 ( set "_skip=" ) else (set "_skip=skip=%position%")
for /f "eol= %_skip% delims=" %%P in (""!var!"") DO (
if "%%~P" neq "" (
set "part=%%~P"
goto :end_for
)
)
set "part="
:end_for
if not defined part (
endlocal
echo Index Out Of Bound >&2
exit /B 2
)
endlocal & if "%~4" NEQ "" (set %~4=%part%) else echo %part%
exit /b 0

FOR /F issue running from a text file + counting up value

Here is something I'm struggeling with:
Title Scanning online computers: && set /a title_count=0
call :next
:next
FOR /F "tokens=1" %%a IN (workstation.txt) do (
title Scanning for online computers: %title_count% / %workstation%
ping -n 1 %%a | find "bytes=" >nul
set /a title_count=title_count+=1
if NOT ERRORLEVEL 1 (
set color=%%a && call includes\what.bat %color_pass% && echo %%a >> logs\reachable.txt
) else (
set color=%%a && call includes\what.bat %color_fail% && echo %%a >> logs\unreachable.txt && echo %%a, offline, % date%, %time% >> logs\offline.txt
)
)
The problem I have here is that the function TITLE is not getting updated while the variable %count_title% is counting up through the script.
set /a title_count+=1
doesn't work either
It's displayed as:
Scanning for online computers 0 / 5
Can sombody tell me what I'm doing wrong here?
Thanks in advance.
Illusion
Hi,
I've tried it the way as suggested:
It finishes the rest of the script when using the last GOTO :EOF
IT doesn't make sense to me, if I remove the last GOTO :eof, only the first row in workstation.txt is getting processed/parsed.
Scanning online computers: && set /a title_count+=1`
call :next
::added as possibly missing
GOTO :EOF
:next
FOR /F "tokens=1" %%a IN (workstation.txt) DO CALL :pingstation %%a
GOTO :EOF
:pingstation
title Scanning for online computers: %title_count% / %workstation%
ping -n 1 %1 | find "bytes=" >nul
set /a title_count+=1
if NOT ERRORLEVEL 1 (
set color=%1 && call includes\what.bat %color_pass% && echo %1 >> logs\reachable.txt
) else (
set color=%1 && call includes\what.bat %color_fail% && echo %1 >> logs\unreachable.txt && echo %1, offline, %date%, %time% >> logs\offline.txt
)
goto :eof
)
Read this: Environment variable expansion occurs when the command is read.
Salient points:
Your variables are expanded right when for command (and its entire body enclosed in parentheses) is parsed.
Use !VARNAME! instead of %VARNAME% to avoid it.
For better portability across OS versions/setups, it's a good idea to stick a setlocal EnableExtensions EnableDelayedExpansion at the beginning of your batch file.
Also, make sure there is a goto (e.g., goto :EOF) after call :next, because the code as posted will run through next one extra time.
You can go with setlocal EnableDelayedExpansion and changing the % syntax to the ! one when addressing vars inside the loop that are initialised within that very loop, just as atzz has suggested.
But there's a different approach. You can simply move the body of the loop to a(nother) subroutine. That way the variables would expand as expected.
Title Scanning online computers: && set /a title_count=0
call :next
::added as possibly missing
GOTO :EOF
:next
FOR /F "tokens=1" %%a IN (workstation.txt) DO CALL :pingstation %%a
GOTO :EOF
:pingstation
title Scanning for online computers: %title_count% / %workstation%
ping -n 1 %1 | find "bytes=" >nul
set /a title_count+=1
if NOT ERRORLEVEL 1 (
set color=%1 && call includes\what.bat %color_pass% && echo %1 >> logs\reachable.txt
) else (
set color=%1 && call includes\what.bat %color_fail% && echo %1 >> logs\unreachable.txt && echo %1, offline, %date%, %time% >> logs\offline.txt
)

Resources