Using variable inside of for loop - windows

The idea is I want to check if a substring is inside of a string with Batch script.
For example I want to check if pass is inside of %rev%. If no for loop is related, I can do:
if /I "%rev:pass=%" neq "%rev%" (
echo String has pass
) else (
echo it doesnt has pass
)
But I don't know how to use this "%rev:pass=%" in side of a for loop when "%rev%" is replaced by %%g
My code is here:
FOR /F "tokens=*" %%g IN (test.txt) do (
if /I "%%g:pass=" neq "%%g" (
echo String has pass
) else (
echo it doesnt has pass
)
)
I need to check each string inside of this test.txt if it has substring pass. Any help is appreciated.
I try to change the form of %%g but still cannot make it happen. The main idea is to check each string in the file, if the string has pass as a sub-string

You can't manipulate for loop variables directly, so you'll need to store them in regular variables first. However, since you can't ordinarily set and use variables inside of sets, you'll need to enable delayed expansion. This can be done by adding setlocal enabledelayedexpansion to the top of your script.
#echo off
setlocal enabledelayedexpansion
FOR /F "tokens=*" %%g IN (test.txt) do (
set "line=%%g"
if /I "!line:pass=!" neq "%%g" (
echo String has pass
) else (
echo it doesnt has pass
)
)

Try this. Will match if the case is UPPER or lower.
It works by string replacement and comparison of before and after.
Also gives a running hit count. Nifty.
setlocal EnableDelayedExpansion
FOR /F "delims= tokens=*" %%g IN (test.txt) do (
set "str1=%%g"
set "str2=!str1:pass=replace!"
if not !str1!==!str2! set /a i+=1 & echo YES - FOUND !i!)
Oh also. the other answer is wrong. The way it's written the two values will NEVER be equal. Try it.

Related

How to use nested FOR loops in batch files

I have some code in which I want to use a FOR loop to handle a set of files.
As part of handling a file there's a FOR /F loop that reads it and appends data to an other file based on the file name.
In order to be able to set the output file name I have delayed variable expansion set on.
This is what the code should look like as I originally intended it to be:
setlocal enabledelayedexpansion
for %%f in (DataFolder\*.Ext) do (
set POI=%%~f
set POI=!JbPOI:DataFolder\=!
set POI=!JbPOI:.Ext=!
for /f "tokens=1,2,3 delims=," %%a in ("%%~f") do (
set CX=%%a
set CY=%%b
set FN=%%c
echo !FN!,9,!CX!,!CY! >> "DataFolder\!POI!.tmp"
)
)
endlocal
This code doesn't work because variable %%a, %%b and %%c never receive a value, %%a always has the same value as %%f.
I have read some articles about this issue but couldn't extract a solution from them that worked.
I have tried several things, none worked so far...
added a dummy outer loop to create variable %%a through %%j explicitly
inner FOR loop taken out and made it a subroutine
inner FOR loop taken out and made it a separate batch file
Can anybody please tell me how this can - or must - be solved?
setlocal enabledelayedexpansion
for %%f in (DataFolder\*.Ext) do (
set POI=%%~f
set POI=!JbPOI:DataFolder\=!
set POI=!JbPOI:.Ext=!
for /f "useback tokens=1,2,3 delims=," %%a in ("%%~f") do (
set CX=%%a
set CY=%%b
set FN=%%c
echo !FN!,9,!CX!,!CY! >> "DataFolder\!POI!.tmp"
)
)
endlocal
I'm not sure if you want to read the file "%%~f" , but I think this is what you need.
Sorry, but for the posted code i don't see the need for delayed expansion. All the needed data is being directly retrieved from the for replaceable parameters
setlocal enableextensions disabledelayedexpansion
for %%f in (DataFolder\*.Ext) do (
(
for /f "usebackq tokens=1-3 delims=," %%a in ("%%~f") do echo(%%c,9,%%a,%%b
) > "DataFolder\%%~nf.tmp"
)
endlocal
If the real code includes something not posted, maybe the answer from npocmaka will better fit in the problem.

remove all double quotes in a file.txt

What I have to do is a batch script that:
_read a file line by line
_remove all the double quote characters writing the result in a file
My attempt was a script like:
for /f "usebackq tokens=*" %%a in ("%GRUPPI3%.txt") do (
SET VARIAB=%%a
SET RESULT=%VARIAB:"=%
echo %RESULT% >> output.txt
)
After some try I realized that the PROBLEM IS THE VARIABLE "VARIAB"!
Doing an echo of VARIAB the result is null or an old value (like an old line read by the variable %%a). (Why "VARIAB" doesn't become a copy of "%%a" as I would expect?)
I can't understand such a behaviour...
Someone know the solution?
Thanks
Cristian
#ECHO OFF
SETLOCAL
(
for /f "usebackq tokens=*" %%a in ("%GRUPPI3%.txt") do (
SET "VARIAB=%%a"
IF DEFINED variab (
SETLOCAL enabledelayedexpansion
SET "RESULT=!VARIAB:"=!"
ECHO(!RESULT!
ENDLOCAL
)
)
)>newfile.txt
GOTO :EOF
This should fix your problem. I changed the detination file to suit my system. If you want to append to the destination file, use >> in place of >

Windows CMD FOR loop

I'm trying to make a code which will get first words from all lines of HELP's output to a variable and echo this variable. Here is my code:
#echo off
set a=
for /F "tokens=1,*" %%i in ('help') do (
set a=%a% %%i
)
echo %a%
But it returns first word from only last line. Why?
Bali C solved your problem as stated, but it looks to me like you are trying to get a list of commands found in HELP.
Some of the commands appear on multiple lines, so you get some extraneous words. Also there is a leading and trailing line beginning with "For" on an English machine that is not wanted.
Here is a short script for an English machine that will build a list of commands. The FINDSTR command will have to change for different languages.
#echo off
setlocal enableDelayedExpansion
set "cmds="
for /f "eol= delims=." %%A in ('help^|findstr /bv "For"') do (
for /f %%B in ("%%A") do set "cmds=!cmds! %%B"
)
set "cmds=%cmds:~1%"
echo %cmds%
EDIT
Ansgar Wiechers came up with a more efficient algorithm to extract just the command names at https://stackoverflow.com/a/12733642/1012053 that I believe should work with all languages. I've used his idea to simplify the code below.
#echo off
setlocal enableDelayedExpansion
set "cmds="
for /f %%A in ('help^|findstr /brc:"[A-Z][A-Z]* "') do set "cmds=!cmds! %%A"
set "cmds=%cmds:~1%"
echo %cmds%
You need to use delayed expansion in your for loop
#echo off
setlocal enabledelayedexpansion
set a=
for /F "tokens=1,*" %%i in ('help') do (
set a=!a! %%i
)
echo %a%
Instead of using %'s around the a variable, you use !'s to use delayed expansion.
Because the echo is outside the do ( ...... )
#echo off
for /F "tokens=1,*" %%i in ('help') do (
echo %%i
)
and no need to print a, you can use directly %%i.
Another very simple example could be a batch like this saved as help1.cmd
#echo off
for /F "tokens=1,*" %%i in ('help') do (
if /I "%%i" EQU "%1" echo %%j
)
and you call this batch like
help1 MKDIR
to get the short help text for the MKDIR command

Get string from file in batch

Task in CMD.
1) How can I compare if string is in string? I checked manual here for "Boolean Test "does string exist ?"" But I can't understand the example or it does not work for me. This piece of code, it is just a try. I try to make a string compare of filter some sting if there is a tag <a> in a line.
FOR /f "tokens=* delims= usebackq" %%c in ("%source%") DO (
echo %%c
IF %%c == "<a" (pause)
)
So while I read a file, it should be paused if there is a link on a line.
2) I have one more ask. I would need to filter the line if there is a specific file in the link, and get content of the link. My original idea was to try to use findstr with regex, but it seems not to use sub-patterns. And next problem would be how to get the result to variable.
set "pdf=0_1_en.pdf"
type "%source%" | grep "%pdf%" | findstr /r /c:"%pdf%.*>(.*).*</a>"
So in summary, I want to go through file and if there is a link like this: REPAIRED: *
<b>GEN 0.1 Preface</b>
I forgot to style this as a code, so the inside of code was not displayed. Sorry.
Warnning: we don't know the path, only the basic filename.
Get the title GEN 0.1 Preface. But you should know, that there are also similar links with same link, which contain image, not a text inside a tag.
Code according Aacini to be changed a little bit:
#echo off
setlocal EnableDelayedExpansion
set "source=GEN 0 GENERAL.html"
set "pdf=0_1_en.pdf"
echo In file:%source%
echo Look for anchor:%pdf%
rem Process each line in %source% file:
for /F "usebackq delims=" %%c in ("%source%") do (
set "line=%%c"
rem Test if the line contain a "tag" that start with "<a" string:
set "tag=!line:*<a=!"
if not "!tag!" == "!line!" (
rem Take the string in tag that end in ">"
for /F "delims=^>" %%a in ("!tag!") do set "link=%%a"
echo Link found: !link!
if "!link!" == "GEN 0.1 Preface" echo Seeked link found
)
)
pause
Still not finished
Although your question is extensive it does not provide to much details, so I assumed several points because I don't know too much about .PDF files, tags, etc.
#echo off
setlocal EnableDelayedExpansion
set "source=GEN 0 GENERAL.html"
set "pdf=0_1_en.pdf"
echo In file: "%source%"
echo Look for anchor: "%pdf%"
rem Process each line in %source% file:
for /F "usebackq delims=" %%c in ("%source%") do (
set "line=%%c"
rem Test if the line contain "<a>" tag:
set "tag=!line:*<a>=!"
if not "!tag!" == "!line!" (
rem Test if "<a>" tag contain the anchor pdf file:
if not "!tag:%pdf%=!" == "!tag!" (
rem Get the value of "<b>" sub-tag
set "tag=!tag:<b>=$!"
set "tag=!tag:</b>=$!"
for /F "tokens=2 delims=$" %%b in ("!tag!") do set title=%%b
echo Title found: "!title!"
)
)
)
pause
Any missing point can be added or fixed, if you give me precise details about them.
EDIT: I fixed the program above after last indications from the OP. I used $ character to get the Title value; if this character may exist in original Tag, it must be changed by another unused one.
I tested this program with this "GEN 0 GENERAL.html" example file:
Line one
<a>href="/Dokumenter/EK_GEN_0_X_en.pdf" class="uline"><b>GEN 0.X Preface</b></a>
Line three
<a>href="/Dokumenter/EK_GEN_0_1_en.pdf" class="uline"><b>GEN 0.1 Preface</b></a>
Line five
and get this result:
In file: "GEN 0 GENERAL.html"
Look for anchor: "0_1_en.pdf"
Title found: "GEN 0.1 Preface"
EDIT: New faster method added
There is a simpler and faster method to solve this problem that, however, may fail if a line contains more than one tag:
#echo off
setlocal EnableDelayedExpansion
set "source=GEN 0 GENERAL.html"
set "pdf=0_1_en.pdf"
echo In file: "%source%"
echo Look for anchor: "%pdf%"
for /F "delims=" %%c in ('findstr /C:"<a>" "%source%" ^| findstr /C:"%pdf%"') do (
set "tag=%%c"
rem Get the value of "<b>" sub-tag
set "tag=!tag:<b>=$!"
set "tag=!tag:</b>=$!"
for /F "tokens=2 delims=$" %%b in ("!tag!") do set title=%%b
echo Title found: "!title!"
)
pause
First, one important question: does this really have to be implemented via a CMD script? Would you be able to go with VBScript, PowerShell, C#, or some other scripting/programming language? CMD is a notoriously painful scripting environment.
Secondly, I'm not sure if this answers your question--it's a bit unclear--but here's a quick trick you can use to see in CMD to see if a given string contains another substring:
setlocal enableextensions enabledelayedexpansion
set PATTERN=somepattern
for /f "delims=" %%f in (somefile.txt) do (
set CURRENT_LINE=%%f
if "!CURRENT_LINE:%PATTERN%=!" neq "!TEMP!" (
echo Found pattern in line: %%f
)
)
The idea is that you try to perform string replacement and see if anything was changed. This is certainly a hack, and it would be preferable if you could instead use a tool like findstr or grep, but if you're limited in your options, something like the above should work.
NOTE: I haven't actually run the above script excerpt, so let me know if you have any difficulty with it.
I have modified the way to do it. I realized that it is better to find name of pdf document first. This is my almost completed solution, but I ask you if you could help me with the last point. The last replacing statement does not work because I need to remove closing tag b. Just to get the title.
#echo off
setlocal EnableDelayedExpansion
set "source=GEN 0 GENERAL.html"
set "pdf=0_1_en.pdf"
echo In file:%source%
echo Look for anchor:%pdf%
rem Process each line in %source% file:
for /F "usebackq delims=" %%c in ("%source%") do (
set "line=%%c"
REM Test if the line contains pdf file I look for:
SET "pdfline=!line:%pdf%=!"
if not "!pdfline!" == "!line!" (
cls
echo Line: !line!
REM Test if the pdfline contains tag b
SET "tagline=!pdfline:*><b>=!"
if not "!tagline!" == "!pdfline!" (
cls
echo ACTUAL LINE: !tagline!
REM Remove closing tag b
SET "title=!tagline:</b*=!"
echo TITLE: !title!
pause
)
)
)
pause
BTW:
The html page I work with is here.
So I ask you to help complete/repair line SET "title=!tagline:</b*=!"

batch find file extension

If I am iterating over each file using :
#echo off
FOR %%f IN (*\*.\**) DO (
echo %%f
)
how could I print the extension of each file? I tried assigning %%f to a temporary variable, and then using the code : echo "%t:~-3%" to print but with no success.
The FOR command has several built-in switches that allow you to modify file names. Try the following:
#echo off
for %%i in (*.*) do echo "%%~xi"
For further details, use help for to get a complete list of the modifiers - there are quite a few!
This works, although it's not blindingly fast:
#echo off
for %%f in (*.*) do call :procfile %%f
goto :eof
:procfile
set fname=%1
set ename=
:loop1
if "%fname%"=="" (
set ename=
goto :exit1
)
if not "%fname:~-1%"=="." (
set ename=%fname:~-1%%ename%
set fname=%fname:~0,-1%
goto :loop1
)
:exit1
echo.%ename%
goto :eof
Sam's answer is definitely the easiest for what you want. But I wanted to add:
Don't set a variable inside the ()'s of a for and expect to use it right away, unless you have previously issued
setlocal ENABLEDELAYEDEXPANSION
and you are using ! instead of % to wrap the variable name. For instance,
#echo off
setlocal ENABLEDELAYEDEXPANSION
FOR %%f IN (*.*) DO (
set t=%%f
echo !t:~-3!
)
Check out
set /?
for more info.
The other alternative is to call a subroutine to do the set, like Pax shows.

Resources