I am trying to check the text in my created array, if I am not using "if" every thing works and i can use "echo" but when I add the "if" command I get "wrong syntax"
#echo off
setlocal ENABLEDELAYEDEXPANSION
set i=0
for /f "delims= " %%a in ('command') do (
set /A i+=1
set list[!i!]=%%~a
)
set Filesx=%i%
rem Display array elements
for /L %%i in (1,1,%Filesx%) do (
if list[%%i] =="some ttext"
echo !list[%%i]!
)
I would consider changing your script accordingly:
#Echo Off
SetLocal EnableDelayedExpansion
Set "i=0"
For /F %%A In ('command') Do (Set/A i+=1
Set list[!i!]=%%~A)
Rem Display array elements
For /L %%A In (1,1,%i%) Do If /I "!list[%%A]!"=="some ttext" Echo !list[%%A]!
Pause
In your script you needed to change if list[%%i] to If /I "!list[%%i]!"
#echo off
setlocal ENABLEDELAYEDEXPANSION
set i=0
for /f "delims= " %%a in ('command') do (
set /A i+=1
set list[!i!]=%%~a
)
set Filesx=%i%
rem Display array elements
for /L %%i in (1,1,%Filesx%) do (
if /i "!list[%%i]!" =="some ttext" (
echo !list[%%i]!
)
)
An if statement requires an exact match (for == or equ) so if you quote one side, you need to quote the other.
also, the action for the if-true condition must be on the same physical line as the if
Related
I'm a novice at batch and been trying to get this to work properly but can't figure out what I'm doing wrong. The counter doesn't increment for some reason?
#echo off
set local enabledelayedexpansion
set /a counter=0
for /F "delims=" %%a in ('dir /b/ad/o "C:\Sources"') do (
for /F "delims=" %%i in ('dir /b/ad/o "C:\Sources\%%a"') do (
set a[%counter]=%%i
set /a counter=counter+1
echo value of counter is: %counter%
)
)
echo array 0 is: %a[0]%
echo array 1 is: %a[1]%
The SET LOCAL should really be SETLOCAL. It's a single command. Also the nested variables should be refernced with !var! and not %var%. If you use %var% it will use the outer scope (and not work correctly).
https://ss64.com/nt/delayedexpansion.html
#ECHO OFF
REM "SETLOCAL" not "SET LOCAL"
SETLOCAL enabledelayedexpansion
SET counter=0
FOR /L %%a IN (1,1,10) DO (
FOR /L %%i IN (1,1,10) DO (
REM USE "!" instead of "%"
SET X[!counter!]=%%i
SET /a counter=!counter! +1
echo value of counter is: !counter!
)
)
ECHO array 0 is: %X[0]%
ECHO array 1 is: %X[1]%
BTW, if you want to have your variables just scoped to your batchfile you should end your script with ENDLOCAL
I am trying to extract a portion of all the filenames(pdf files) in the current directory.
The length of filenames vary except for the last portion(datetime and extension) which will always be 16 characters. The remaining part will always have different lengths. Even the portion I require may have varying lengths.
I tried using lastIndexOf function obtained here.
filename eg : academyo-nonpo-2582365-082416051750.pdf
I want to extract the section in Bold.
I tried trimming the last 17 characters(this portion will always have a fixed length.) first and then tried to obtain the last Index Of '-'(since the fist portion can have variable character length.) and trim the characters until that position, which should return the required portion of the filename.
#echo off
Setlocal enabledelayedexpansion
For %%# in ("%~dp0\*.pdf") Do (
Set "File=%%~nx#"
Set "File=!File:~0,-17!"
Set "lio2="
#echo on
echo !File!
#echo off
call :lastindexof !File! - lio2
Set "File=!File:~%lio%!"
)
Pause&Exit
:lastindexof [%1 - string ; %2 - find last index of ; %3 - if defined will store the result in variable with same name]
#echo off
setlocal enableDelayedExpansion
set "str=%~1"
set "p=!str:%~2=&echo.!"
set "splitter=%~2"
set LF=^
rem ** Two empty lines are required
echo off
for %%L in ("!LF!") DO (
for /f "delims=" %%R in ("!splitter!") do (
set "var=!str:%%R=%%L!"
)
)
for /f delims^=^" %%P in ("!var!") DO (
set "last_part=%%~P"
)
if "!last_part!" equ "" if "%~3" NEQ "" (
echo "not contained" >2
endlocal
set %~3=-1
exit
) else (
echo "not contained" >2
endlocal
set argv=original
set $strLen=for /L %%n in (1 1 2) do if %%n==2 (%\n%
for /F "tokens=1,2 delims=, " %%1 in ("!argv!") do (%\n%
set "str=A!%%~2!"%\n%
echo -1
)
setlocal DisableDelayedExpansion
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
set "len=0"%\n%
for /l %%A in (12,-1,0) do (%\n%
set /a "len|=1<<%%A"%\n%
for %%B in (!len!) do if "!str:~%%B,1!"=="" set /a "len&=~1<<%%A"%\n%
)%\n%
for %%v in (!len!) do endlocal^&if "%%~b" neq "" (set "%%~1=%%v") else echo %%v%\n%
) %\n%
) ELSE setlocal enableDelayedExpansion ^& set argv=,
%$strlen% strlen,str
%$strlen% plen,last_part
%$strlen% slen,splitter
set /a lio=strlen-plen-slen
endlocal & if "%~3" NEQ "" (set %~3=%lio%) else echo %lio%
exit /b
The reference of the variable passed to the function as the 3rd parameter doesn't seem to be returning the required value.
I dunno what is wrong here.
To get the section in bold then:
Example#
#Echo Off
SetLocal EnableDelayedExpansion
For %%# in ("%~dp0*.pdf") Do (
Set "File=%%~n#"
Set "File=!File:~-20,7!"
Echo=!File!%%~x#)
Pause
Okay what about?
#Echo Off
SetLocal EnableDelayedExpansion
For %%# in ("%~dp0*.pdf") Do (
Set "File=%%~n#"
Set "File=!File:~,-13!"
Call :Sub "!File:-=\!%%~x#")
Pause
:Sub
Echo=%~nx1
To extract the portion in between the last hyphen and the next-to-last one, you could use the following script (provide the strings/files as command line arguments):
#echo off
setlocal EnableExtensions EnableDelayedExpansion
set "SEP=-"
for %%A in (%*) do (
set "ITEM=%%~A"
set "PREV="
if defined ITEM (
for %%B in ("!ITEM:%SEP%=" "!") do (
set "PREV=!PART!"
set "PART=%%~B"
)
if defined PREV (
echo(!PREV!
)
)
)
endlocal
exit /B
This approach basically replaces every - by the standard cmd tokenisation character SPACE and iterates through the resulting string using a standard for loop (no /F option). The currently iterated part is stored in variable PART, whose content is first copied into PREV to gain a delay of one loop iteration. So the next-to-last portion is finally stored in PREV.
Note that this script might return unexpected results in case the strings/files contain exclamation marks because of delayed expansion.
Have a look on this answer. Thought is to first count the number of tokens (you still do have to trim the string before this) and then get the last token.
In the first loop where it says "tokens=1*" , you have to edit it to the following: "tokens=1* delims=-" and in the second loop add delims=- as well after %i%. It should be looking like this in total with your script:
#echo off
SetLocal EnableDelayedExpansion
For %%# in ("%~dp0\*.pdf") Do (
Set "File=%%~nx#"
Set "File=!File:~0,-17!"
Set "lio2="
#echo on
echo !File!
#echo off
call:subfunction !File! - lio2
Set "File=!File:~%lio%!"
)
:subfunction
set var1=%1
set var2=%var1%
set i=0
:loopprocess
for /F "tokens=1* delims=-" %%A in ( "%var1%" ) do (
set /A i+=1
set var1=%%B
goto loopprocess )
for /F "tokens=%i% delims=-" %%G in ( "%var2%" ) do set last=%%G
echo %last%
REM do what you want with last here!
I tested it and it seems to be working correctly even with something like ac-ade-myo-n-on-po-15482729242321654-082416051750.pdf, however after finishing correctly, it give an error message one time with a syntax error I could not find...
If you can ignore that error (everything else works), this might help.
I'm making a batch script to stop several services , however i get the syntax is incorrect error at second FOR which loops in serviceList.TEMP
setlocal EnableDelayedExpansion
setlocal enableExtensions
::queryex output file
sc queryex>services.TEMP
find /i /N "DISPLAY_NAME: Hotspot" services.TEMP>tmp1.TEMP
FOR /F "skip=2" %%G in (tmp1.TEMP) do (
set num=%%G
set num=!num:~1,3!
echo !num!>serviceList.TEMP
)
FOR %%X in (serviceList.TEMP) do (
set /a "SKIP_LINES=%%G+7"
set secondForFilter="skip=%SKIP_LINES%"
FOR /F %secondForFilter% %%Z in (services.TEMP) do (
call debug.cmd REM debug.cmd -> echo debug pause>nul
set serv=%%Z
set "serv=!serv: =!" REM Extract PID
set "serv=!serv::=!" REM Extract PID
set procID=!serv!
taskkill /pid %procID% /f >>debug.txt 2>>debug.txt
goto secondLoopEnd
)
:secondLoopEnd
)
del /S *.TEMP >>debug.txt 2>>debug.txt
the problem is here:
FOR %%X in (serviceList.TEMP) do (
set /a "SKIP_LINES=%%G+7"
set secondForFilter="skip=%SKIP_LINES%"
FOR /F %secondForFilter% %%Z in (services.TEMP) do (
call debug.cmd REM debug.cmd -> echo debug pause>nul
the usual approach when you set value in brackets context is to use delayed expansion but it wont work for parametrized for options.
Here you'll need a subroutine.
And you have GOTO in the for loop. GOTO breaks for context and the loops will be not called after goto is executed.
And rem cannot be used on the same line as the code without "&"
Consider something like this (though I cannot check the logic of the bat):
setlocal EnableDelayedExpansion
setlocal enableExtensions
::queryex output file
sc queryex>services.TEMP
find /i /N "DISPLAY_NAME: Hotspot" services.TEMP>tmp1.TEMP
FOR /F "skip=2" %%G in (tmp1.TEMP) do (
set num=%%G
set num=!num:~1,3!
echo !num!>serviceList.TEMP
)
FOR %%X in (serviceList.TEMP) do (
call :subroutine %%G
)
del /S *.TEMP >>debug.txt 2>>debug.txt
exit /b %errorlevel%
:subroutine
setlocal enableDelayedExpansion
set /a skiplines=%~1+7
set "filter="skip=%skiplines%""
FOR /F %filter% %%Z in (services.TEMP) do (
call debug.cmd
set serv=%%Z
rem extract PID
set "serv=!serv: =!"
set "serv=!serv::=!"
set procID=!serv!
taskkill /pid !procID! /f >>debug.txt 2>>debug.txt
goto :break_for
)
:break_for
endlocal
exit /b
Should the > in your echo to serviceList.TEMP be a >> so that you append to the file?
echo !num!>>serviceList.TEMP
In which case, you should also ensure that the file is deleted prior to the appending operations.
Also, I assume you missed the /F from your FOR loop, as you're trying to read the lines of the serviceList.TEMP file, yes?
FOR %%X in (serviceList.TEMP) do (
Should be...
FOR /F %%X in (serviceList.TEMP) do (
?
Also, you can append to the same file with both std out and err by doing this...
someprocesshere 1> out.log 2>&1
I'm trying to make a loop that goes through a file with filenames on each line, set the first filename as a variable and execute the rest if the script. Then take the second line and do the same.
etc. etc.
The problem is that it only does the first line of filenames.txt
#echo off
for /F "tokens=*" %%G in (filenames.txt) do (
set filename=%%G
script
script
script
)
pause
It has be a batch file.
The whole script:
#ECHO OFF
for /F "tokens=*" %%G in (filenames.txt) do (
SET FileName=%%G
SET Word1="ts_confirmImplicitSAMM.gram"
SET Word2="SWIrcnd"
for /f "tokens=3" %%f in ('find /c /i %Word1% %FileName%') do set PairsToShow=%%f
SET /a Lines1=0, Lines2=0
FOR /f "delims=" %%a IN ('findstr "%Word1%" "%FileName%"') DO (
SET "str=%%a"
SET /a Lines1+=1
SETLOCAL enabledelayedexpansion
SET "$1!Lines1!=!str!"
FOR /f "tokens=1*delims==" %%b IN ('set "$1"') DO (IF "!"=="" endlocal)&SET "%%b=%%c"
)
FOR /f "delims=" %%a IN ('findstr "%Word2%" "%FileName%"') DO (
SET "str=%%a"
SET /a Lines2+=1
SETLOCAL enabledelayedexpansion
SET "$2!Lines2!=!str!"
FOR /f "tokens=1*delims==" %%b IN ('set "$2"') DO (IF "!"=="" endlocal)&SET "%%b=%%c"
)
SET /a Lines=Lines1+Lines2
ECHO(%Lines% lines read from %FileName%.
IF %Lines1% leq %Lines2% (SET /a MaxPairs=Lines1) ELSE SET /a MaxPairs=Lines2
IF %PairsToShow% gtr %MaxPairs% (
ECHO only text for %MaxPairs% pairs NOT %PairsToShow% :/
GOTO :END
)
(FOR /l %%a IN (1,1,%PairsToShow%) DO (
SETLOCAL ENABLEDELAYEDEXPANSION
CALL SET "Line1=%%$1%%a%%"
CALL SET "Line2=%%$2%%a%%"
<NUL SET /p "=!Line1!"
ECHO !Line2!
ENDLOCAL
))>> result1.txt
ENDLOCAL
TYPE result1.txt| FINDSTR /V EVNT=SWIgrld >> result.txt
DEL result1.txt
PAUSE
)
Without seeing the rest of your script... you probably need to do 1 of 2 things:
Use SETLOCAL ENABLEDELAYEDEXPANSION (as 2nd line of your script) and then reference the variable filename as !filename! instead of %filename% to use the run-time value instead of the load-time value. But that could cause other problems, depending on what goes on in "script".
Just use %%G instead of filename
I am referring to below threat Batch files: How to read a file?. For retrieving the line by line from a text file. I am using the below script:
#echo off
SETLOCAL DisableDelayedExpansion
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ paths.txt"`) do (
set "var=%%a"
SETLOCAL EnableDelayedExpansion
set "var=!var:*:=!"
echo !var!
ENDLOCAL
)
Code is working fine! The values in !var! can not assign to any variable. :( I struct there, Please anyone help to read line by line and I wish to assign to some variable and want to manipulate that variable. Please help to solve this situation.
Update:
#ECHO off
CLS
SET PROJ_DIR=D:\workspace\proj
SET PROMO_DIR=D:\TEST
SET SOURCE_CODE=\Source Code
SETLOCAL DisableDelayedExpansion
for /f %%a in (paths.txt) do (
SET "var=%%a"
SETLOCAL EnableDelayedExpansion
set "var=!var:*:=!"
set FILE_PATH=!var://www.domain.com/path/dir=!
SET FILE_PATH=!FILE_PATH:/=\!
SET PROMO_FILE_PATH=!PROMO_DIR!!SOURCE_CODE!!FILE_PATH!
FOR %%i IN ("!PROMO_FILE_PATH!") DO SET FOLDER_PATH=%%~dpi
FOR %%i IN ("!PROMO_FILE_PATH!") DO SET FILE_NAME=%%~nxi
IF EXIST "!FOLDER_PATH!" GOTO F3
MKDIR "!FOLDER_PATH!"
:F3
IF NOT EXIST "!PROJ_DIR!!FILE_PATH!" GOTO F4
COPY "!PROJ_DIR!!FILE_PATH!" "!FOLDER_PATH!"
:F4
ECHO Cannot find the file under "!PROJ_DIR!!FILE_PATH!"
ENDLOCAL
)
SET CLOSE_CONFIRM=
SET /P CLOSE_CONFIRM=Press any key to close the window...%=%
paths.txt
//www.domain.com/path/dir/dir1/dir2/file1.txt
//www.domain.com/path/dir/dir1/dir2/file2.txt
//www.domain.com/path/dir/dir1/dir2/file3.txt
//www.domain.com/path/dir/dir1/dir2/file4.txt
//www.domain.com/path/dir/dir1/dir3/file1.txt
Command Output
1 file(s) copied.
Cannot find the file under "D:\workspace\proj\dir1\dir2\file1.txt"
1 file(s) copied.
Cannot find the file under "D:\workspace\proj\dir1\dir2\file2.txt"
Press any key to close the window...
thanks..
The key is the delayed expansion, expand your variables inside of parenthesis always with ! not with %.
A sample that changes X with Y
#echo off
SETLOCAL DisableDelayedExpansion
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ paths.txt"`) do (
set "var=%%a"
SETLOCAL EnableDelayedExpansion
set "var=!var:*:=!"
set "myVar=!var!"
set "myVar=!myVar:X=Y!"
echo X replaced with Y =!myVar!
ENDLOCAL
)
In your updated version the goto :label stops the for-loop immediatly
Better rewrite it to IF-Blocks
IF NOT EXIST "!FOLDER_PATH!" (
MKDIR "!FOLDER_PATH!"
)
IF EXIST "!PROJ_DIR!!FILE_PATH!" (
COPY "!PROJ_DIR!!FILE_PATH!" "!FOLDER_PATH!"
) ELSE
(
ECHO Cannot find the file under "!PROJ_DIR!!FILE_PATH!"
)
The other answers here cover the tricky bits of delayed expansion in this code. I want to add that you can often avoid most delayed expansion problems by rolling the parentheses out into a subroutine.
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ paths.txt"`) do call :HandlePath %%a
goto :eof
================
:HandlePath
set "var=%*"
set "var=%var:*:=%"
echo %var%
goto :eof
I find this code easier to maintain because each line is parsed an executed exactly when you would expect.
If you want to read each line and manipulate it:
SETLOCAL EnableDelayedExpansion
FOR /F "tokens=*" %%a IN (paths.txt) DO (
set var=%%a
ECHO %var%
PAUSE
)
ENDLOCAL
If you are trying to search a string from a file and manipulate it:
SETLOCAL EnableDelayedExpansion
FOR /F "tokens=* usebackq" %%a IN (`FIND /I 'string to search for' "C:\folder\paths.txt"`) DO (
set var=%%a
ECHO %var%
PAUSE
)
ENDLOCAL
If you are trying to search a string and manipulate each word in the string:
SETLOCAL EnableDelayedExpansion
FOR /F "usebackq tokens=1-999 delims= " %%a IN (`FIND /I 'string to search for' "C:\folder\paths.txt"`) DO (
REM %%a = first word %%b = second word etc. through the alphabet
set var1=%%a%%b%%c
set var2=%%d
ser var3=%%e
ECHO %var1% %var2% %var3%
PAUSE
)
ENDLOCAL
This works for me:
#echo off
SETLOCAL EnableDelayedExpansion
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ paths.txt"`) do (
set var=%%a
set var=!var:*:=!
echo !var!
)
ENDLOCAL