How do I substring a dynamic variable value in windows batch scripting - batch-file

Not able to substring the dynamic variable inside forloop in Windows batch script.
I have the properties file in my git hub in the below format.
"collectionName=TestCollectionRun.json=test"
So I have written the below code to fetch this values.But the requirement is that I need to strip of the '.json' part from collection name.With the below code I am not able to set/echo that value.Can you please help on this!
#ECHO ON
:BEGIN
IF EXIST "test.properties" ECHO Found properties file, reading file..
SET props=test.properties
setlocal EnableDelayedExpansion
For /F "delims== tokens=1,2,3" %%G in (%props%) Do (
if "%%I" EQU "test" if "%%G" EQU "collectionName" SET collName=%%H(
SET finalCollName=%collName%:~0,-5
ECHO %finalCollName%
)
)
:END
We need the ECHO to return "TestCollectionRun".currently its not returning anything.

For /F "delims== tokens=1,2,3" %%G in (%props%) Do (
if "%%I" EQU "test" if "%%G" EQU "collectionName" SET "collName=%%~nH"&echo %%~nH
)
ECHO %CollName%
Note the second ) is now redundant. Your problem has to do with delayedexpansion which you are invoking but not using. call %%collname%% within the for loop would have shown the value after assignment if required.
This code works by interpreting %%H as a filename and assigning simply the name part of %%H (%%~nH)

Given a line content of collectionName=TestCollectionRun.json=test, here's a quick rewrite of what I think you're tring to do:
#Echo Off
Set "props=test.properties"
If Not Exist "%props%" (
Echo Properties file not found!
Echo Exiting..
Timeout /T 3 /NoBreak >NUL
Exit /B
)
Echo Found properties file, reading file..
For /F "UseBackQ Tokens=1-3 Delims==" %%A In ("%props%") Do (
If /I "%%C" == "test" If /I "%%A" == "collectionName" Echo %%~nB
)
Pause
If you wanted to do something with the collection name within the loop then you would probably need to use delayed expansion:
#Echo Off
SetLocal DisableDelayedExpansion
Set "props=test.properties"
If Not Exist "%props%" (
Echo Properties file not found!
Echo Exiting..
Timeout /T 3 /NoBreak >NUL
Exit /B
)
Echo Found properties file, reading file..
For /F "UseBackQ Tokens=1-3 Delims==" %%A In ("%props%") Do (
If /I "%%C" == "test" If /I "%%A" == "collectionName" (
Set "collName=%%B"
SetLocalEnableDelayedExpansion
Echo !collName!
Rem Perform substring task on the variable named collName
Set "finalCollName=!collName%:~0,-5!"
Echo !finalCollName!
EndLocal
)
)
Pause
Note, these answers will not work, as is, if your string is surrounded by doublequotes, (as in your question body), or if the line content differs (e.g. begins with spaces or tabs).
[Edit /]
Looking at your 'after the fact' question in the comments, it is clear that you do not need to substring the variable at all, so should use the first method posted:
Echo Found properties file, reading file..
For /F "UseBackQ Tokens=1-3 Delims==" %%A In ("%props%") Do (
If /I "%%C" == "test" If /I "%%A" == "collectionName" (
newman run "%%B" -e "%envName%" --insecure --reporters cli,htmlextra --reporter-htmlextra-export "newman\%BUILD_NUMBER%\%%~nB.html" --disable-unicode
)
)
Pause
This assumes that both %envName% and %BUILD_NUMBER% have been previously defined correctly.

Related

check for spaces in file name inside of for loop in batch file

I have a batch script that is calling a VBscript file. It reiterates through all files in a watched folder.
It needs to verify if the file name has spaces in it and if so reject the file and not process it with the VBS.
I must have an error on the code as I get the error message:
ELSE was not expected at this time.
I have looked at the documentation and searched for the answer for quite some time, including this question: check "IF" condition inside FOR loop (batch/cmd)
But still, I can't see what is wrong in my syntax:
#ECHO OFF
setlocal ENABLEDELAYEDEXPANSION
call :ReadIni Infolder inFolder
call :ReadIni Outfolder outFolder
echo %inFolder%
echo %outFolder%
pause
:StartLoop
FOR %%I in (%inFolder%\*.srt) DO (
ECHO %%I
ECHO %%~nxI
SET TESTNAME=%%~nxI
ECHO !TESTNAME!
ECHO !TESTNAME: =_!
PAUSE
IF NOT !TESTNAME!==!TESTNAME: =_! (
move "%~sdp0%%~nxI" "%outFolder%\ERROR_IN_FILE_NAME_%%~nxI"
) ELSE (
copy /y "%%I" "%~sdp0%%~nxI"
%~sdp0SRToffset.vbs "%~sdp0%%~nxI" "%~sdp0%%~nxI"
IF %ERRORLEVEL%==1 (
Goto StartLoop
) else (
move "%~sdp0%%~nxI" "%outFolder%\"
move "%~sdp0QC_%%~nxI" "%outFolder%\"
del "%%I"
)
)
)
timeout /t 1
goto StartLoop
:ReadIni
FOR /F "tokens=2 delims==" %%a in ('find "%~1=" config.ini') do set %~2=%%a
exit /b
Any help would be appreciated.
IF NOT "!TESTNAME!"=="!TESTNAME: =_!" (
...
IF %ERRORLEVEL%==1 (
Quoting the strings causes cmd to regard the string as a single entity.
Note that the following if %errorlevel% will be executed using the value of errorlevel at :startloop. (See delayed expansion for reasoning.)
Cure by using if !errorlevel!==1 (. (Using the runtime value of errorlevel as established by the vbs routine.)

How can we split string using windows bat

How can we split string using windows bat script?
for below .bat code snippet
#echo off & setlocal EnableDelayedExpansion
set j=0
for /f "delims=""" %%i in (config.ini) do (
set /a j+=1
set con!j!=%%i
call set a=%%con!j!%%
echo !a!
(echo !a!|findstr "^#">nul 2>nul && (
rem mkdir !a!
) || (
echo +)
rem for /f "tokens=2" %%k in(config.ini) do echo %%k
)
)
pause
below config file
Q
What's wrong when I del rem at the begin of rem for /f "tokens=2" %%k in(config.ini) do echo %%k
How can I get the /path/to/case and value as a pair?
for /f xxxx in (testconfig.ini) do (set a=/path/to/case1 set b=vaule1)
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q43407067.txt"
set j=0
for /f "delims=""" %%i in (%filename1%) do (
set /a j+=1
set con!j!=%%i
call set a=%%con!j!%%
echo !a! SHOULD BE EQUAL TO %%i
(echo !a!|findstr "^#">nul 2>nul && (
echo mkdir !a!
) || (
echo +)
for /f "tokens=2" %%k IN ("%%i") do echo "%%k"
for /f "tokens=1,2" %%j IN ("%%i") do echo "%%j" and "%%k"
)
)
ECHO ----------------------------
SET con
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
I used a file named q43407067.txt containing your data for my testing.
(These are setting that suit my system)
SO - to address your problems:
because the ) on that line closes the ( on the previous. The ) on that line closes the ( on the one prior. (I changed the rem to an echo so that the code would produce something visible) The first ( on the (echo !a! line is closed by the ) on the line following the (now) two for /f commands. and the ( on the for..%%i..do( is closed by the final ) before the echo -----
You can't delete that ) because it's participating in a parenthesis-pair.
You need a space between the in and the (.
I've shown a way. See for /?|more from the prompt for documentation (or many articles here on SO)
In your code, !a! is the same as %%i - so I've no idea why you are conducting all the gymnastics - doubtless to present a minimal example showing the problem.
Note that since the default delimiters include Space then if any line contains a space in the /path/to/case or value then you'll have to re-engineer the approach.
I' not sure if I understand what exactly it is you need, so what follows may not suit your needs:
#Echo Off
SetLocal EnableDelayedExpansion
Set "n=0"
For /F "Delims=" %%A In (testConfig.ini) Do (Set "_=%%A"
If "!_:~,1!"=="#" (Set/A "n+=1", "i=0"
Echo=MD %%A
Set "con[!n!]!i!=%%A") Else (For /F "Tokens=1-2" %%B In ('Echo=%%A'
) Do (Set/A "i+=1"
Set "con[!n!]!i!=%%B"&&Set/A "i+=1"&&Set "con[!n!]!i!=%%C")))
Set con[
Timeout -1
GoTo :EOF
remove Echo= on line 6 if you are happy with the output and really want to create those directories

Windows Batch FOR Loop improvement

I have a batch to check the duplicate line in TXT file (over one million line) with 13MB, that will be running over 2hr...how can I speed up that? Thank you!!
TXT file
11
22
33
44
.
.
.
44 (over one million line)
Existing Batch
setlocal
set var1=*
sort original.txt>sort.txt
for /f %%a in ('type sort.txt') do (call :run %%a)
goto :end
:run
if %1==%var1% echo %1>>duplicate.txt
set var1=%1
goto :eof
:end
This should be the fastest method using a Batch file:
#echo off
setlocal EnableDelayedExpansion
set var1=*
sort original.txt>sort.txt
(for /f %%a in (sort.txt) do (
if "%%a" == "!var1!" (
echo %%a
) else (
set "var1=%%a"
)
)) >duplicate.txt
This method use findstr command as in aschipfl's answer, but in this case each line and its duplicates are removed from the file after being revised by findstr. This method could be faster if the number of duplicates in the file is high; otherwise it will be slower because the high volume data manipulated in each turn. Just a test may confirm this point...
#echo off
setlocal EnableDelayedExpansion
del duplicate.txt 2>NUL
copy /Y original.txt input.txt > NUL
:nextTurn
for %%a in (input.txt) do if %%~Za equ 0 goto end
< input.txt (
set /P "line="
findstr /X /C:"!line!"
find /V "!line!" > output.txt
) >> duplicate.txt
move /Y output.txt input.txt > NUL
goto nextTurn
:end
#echo off
setlocal enabledelayedexpansion
set var1=*
(
for /f %%a in ('sort q42574625.txt') do (
if "%%a"=="!var1!" echo %%a
set "var1=%%a"
)
)>"u:\q42574625_2.txt"
GOTO :EOF
This may be faster - I don't have your file to test against
I used a file named q42574625.txt containing some dummy data for my testing.
It's not clear whether you want only one instance of a duplicate line or not. Your code would produce 5 "duplicate" lines if there were 6 identical lines in the source file.
Here's a version which will report each duplicated line only once:
#echo off
setlocal enabledelayedexpansion
set var1=*
set var2=*
(
for /f %%a in ('sort q42574625.txt') do (
if "%%a"=="!var1!" IF "!var2!" neq "%%a" echo %%a&SET "var2=%%a"
set "var1=%%a"
)
)>"u:\q42574625.txt"
GOTO :EOF
Supposing you provide the text file as the first command line argument, you could try the following:
#echo off
for /F "usebackq delims=" %%L in ("%~1") do (
for /F "delims=" %%K in ('
findstr /X /C:"%%L" "%~1" ^| find /C /V ""
') do (
if %%K GTR 1 echo %%L
)
)
This returns all duplicate lines, but multiple times each, namely as often as each occurs in the file.

Batch-file for-loop and use of delims

I have created a batch file in a windows server to parse the name of the files stored in a folder.
The name of the file contains a set of parameters splitted by the hyphen, e.g.
ACC-INV-APR-2015
I need to check the syntax correctness of the first two parameters (department and document type) e.g. I would avoid that the hyphen is inserted more than a time in the file name.
On the basis of the check, the files with wrong syntax will be moved to a folder.
We have to consider that, apart the first two parameters that are mandatory, the other ones could be skipped and therefore the file name could have some repetitive hypens after the first two parameters, e.g.
FIN-DOC-APR-2015--MFH-P01
We would avoid to have some file name like: FIN--DOC-APR-2015-MFH-P01
I have created the following batch file but I don't know how to skip the filename with wrong syntax....
Thank you.
setlocal EnableDelayedExpansion
set source=\\fileserver\share$\archive
set dest_ok=\\fileserver\share$\fileok
set dest_not=\\fileserver\share$\error
FOR /R %source% %%f in (*.*) do call :Proc1 "%%f"
goto End
:Proc1
Set filename=%1%
For %%A in (%filename%) do (
Set Folder="%%~dpA"
Set Name=%%~nxA
)
for /f "tokens=1,2 delims=- " %%a in ("%Name%") do call :Proc2 %%a %%b
goto :eof
:Proc2
set department=%1
set typedoc=%2
FINDSTR /x "%department%" c:\0_scripts\arch\departments.txt
if %errorlevel%==0 FINDSTR /x "%typedoc%" c:\0_scripts\arch\typedocs.txt
if %errorlevel%==0 move /Y %filename% %dest_ok%
if %errorlevel%==1 move /Y %filename% %dest_not%
goto :eof
:End
Sounds like a job for regular expressions. The Windows utility findstr will let you match based on a regular expression. It exits status 0 if found, non-zero otherwise. This lends itself to conditional execution. In a cmd console, enter findstr /? for details on supported regexp syntax.
It'll also speed things up to cache the contents of departments.txt and typedocs.txt into variables, rather than open, read, close, repeat for each file checked.
So, with that in mind, here's how I'd do it:
#echo off
setlocal
set "source=\\fileserver\share$\archive"
set "dest_ok=\\fileserver\share$\fileok"
set "dest_not=\\fileserver\share$\error"
set "departments.txt=c:\0_scripts\arch\departments.txt"
set "typedocs.txt=c:\0_scripts\arch\typedocs.txt"
setlocal enabledelayedexpansion
for /f "usebackq delims=" %%I in ("%departments.txt%") do set "dept=%%~I;!dept!"
for /f "usebackq delims=" %%I in ("%typedocs.txt%") do set "type=%%~I;!type!"
endlocal & set "dept=%dept%" & set "type=%type%"
for /r "%source%" %%I in (*) do (
rem // Does filename match /^[a-z]+-[a-z]+/i ?
echo %%~nxI | findstr /i "^[a-z][a-z]*-[a-z][a-z]*" >NUL && (
rem // Yep. Check whether department and doc type is in allowed list.
for /f "tokens=1-2 delims=- " %%a in ("%%~nxI") do (
// if %dept% doesn't equal itself with %%~a removed, and so on...
setlocal enabledelayedexpansion
if not "%dept%"=="!dept:%%~a=!" if not "%type%"=="!type:%%~b=!" (
// All checks passed. Moved to OK folder.
move /y "%%~fI" "%dest_ok%"
)
endlocal
)
)
// If the file hasn't been moved by now, it must've failed a test.
if exist "%%~fI" move /y "%%~fI" "%dest_not%"
)
C:\0_scripts\arch>(
echo MFH3-FHW-20150529-F001MD14895-20301231-V01-OP20-TRIFLEX-CP1_H--.pdf | findstr /i "^[a-z][a-z]*-[a-z][a-z]*" 1>N
UL && (for /F "tokens=1-2 delims=- " %a in ("MFH3-FHW-20150529-F001MD14895-20301231-V01-OP20-TRIFLEX-CP1_H--.pdf") do (
setlocal enabledelayedexpansion
if not "TEF6;TEF10;QMM8;QMM73;QMM72;QMM71;QMM7;QMM6;QMM13;QMM1;QMM;MFP2;MFP1;MFH3;MFH2;MFH1;MFH ;MFG3;MFG22;MFG21;MFG2;
MFG11;MFG1;MFG;MFB;HSE;COS;" == "!dept:%~a=!" if not "WPL;WP;WBP;WB;WAL;WAG;WA;VTL;VTK;VDP;VBT;VBL;VB;VAW;VAP;VA;UVA;UMV
;TSS;TRN;TKU;TDC;SYM;SWD;SWC;SW;SVS;SVA;SV;STR;STL;STF;STB;SPC;SBT;SAM;RTZ;RTP;RPL;RP;RNO;RHW;RAW;QMP;QMA;QM;QBG;QB;QAM;
PZB;PUM;PRV;PRS;PRJ;PRA;PQP;PPM;PPK;PP;PNR;PLB;PH;PFH;PDV;PDR;PDC;PDB;PAP;PAL;PAG;OPS;OPL;OEE;NOR;NKA;MUB;MSZ;MON;MOD;MB
B;MNT;LZT;LZS;LZN;LPV;LPN;LPL;LPC;LPA;LHT;LDP;LBA;KSB;KPV;KPA;KOE;KOB;KBU;KBL;KB;IAM;HZG;HZ;HSE;HRB;HFG;HF;HE;HAZ;GMD;GE
Z;GBB;FVT;FRM;FPL;FPK;FPI;FPA;FP;FMP;FME;FMD;FMA;FLP;FLB;FIM;FHW;FGY;FGV;FGS;FGP;FGL;FGK;FGE;FGD;FGB;FGA;FDA;FA;EZZ;EWZ;
EWS;EVT;EV;ETZ;ETL;ESZ;EPB;EP;ECM;DVL;ECR;DV;DRX;DRW;DRV;DRQ;DRK;DRF;DMD;DIF;DLP;DER;DDI;DBL;DB;DAT;D01;CPC;CIP;CHL;CE;C
AP;BVT;BVS;BVB;BV;BUG;BSV;BST;BSS;BS;BPZ;BLD;BDL;BBL;BBD;BB;BAL;BAD;ANH;AGZ;AFK;AEN;AED;AAW;AA;" == "!type:%~b=!" (
move /y "\\server1\digit$\deposito\MFH3\MFH3-FHW-20150529-F001MD14895-20301231-V01-OP20-TRIFLEX-CP1_H--.pdf" "\\server1\digit$\errori"
pause
)
endlocal
) )
if exist "\\server1\digit$\deposito\MFH3\MFH3-FHW-20150529-F001MD14895-20301231-V01-OP20-TRIFLEX-CP1_H--.pdf" move
/y "\\server1\digit$\deposito\MFH3\MFH3-FHW-20150529-F001MD14895-20301231-V01-OP20-TRIFLEX-CP1_H--.pdf" "\\server11\digit$\ok"
pause
)
1 file(s) moved.
Press any key to continue . . .
Blockquote
I have changed the script and came back to your original version .
This is the output of the batch file when a file correct is processed:
if exist "\server1\digit$\deposito\MFH3\MFH3--FHW-20150512-F01MD14861-20301231-V02-OP20-TRIFLEX-CP1H--.pdf" move
/y "\server1\digit$\deposito\MFH3\MFH3--FHW-20150512-F01MD14861-20301231-V02-OP20-TRIFLEX-CP1H--.pdf" "\server1\
digit$\errori"
pause
)
1 file(s) moved.
Press any key to continue . . .
C:\0_scripts\arch>(
echo MFH3-AFK-20150511-F01MD12340-20301231-V07-OP20-TRIFLEX-CP1_H--.pdf | findstr /i "^[a-z][a-z]-[a-z][a-z]" 1>NU
L && (for /F "tokens=1-2 delims=- " %a in ("MFH3-AFK-20150511-F01MD12340-20301231-V07-OP20-TRIFLEX-CP1_H--.pdf") do (
setlocal enabledelayedexpansion
if not "TEF6;TEF10;QMM8;QMM73;QMM72;QMM71;QMM7;QMM6;QMM13;QMM1;QMM;MFP2;MFP1;MFH3;MFH2;MFH1;MFH ;MFG3;MFG22;MFG21;MFG2;
MFG11;MFG1;MFG;MFB;HSE;COS;" == "!dept:%~a=!" if not "WPL;WP;WBP;WB;WAL;WAG;WA;VTL;VTK;VDP;VBT;VBL;VB;VAW;VAP;VA;UVA;UMV
;TSS;TRN;TKU;TDC;SYM;SWD;SWC;SW;SVS;SVA;SV;STR;STL;STF;STB;SPC;SBT;SAM;RTZ;RTP;RPL;RP;RNO;RHW;RAW;QMP;QMA;QM;QBG;QB;QAM;
PZB;PUM;PRV;PRS;PRJ;PRA;PQP;PPM;PPK;PP;PNR;PLB;PH;PFH;PDV;PDR;PDC;PDB;PAP;PAL;PAG;OPS;OPL;OEE;NOR;NKA;MUB;MSZ;MON;MOD;MB
B;MNT;LZT;LZS;LZN;LPV;LPN;LPL;LPC;LPA;LHT;LDP;LBA;KSB;KPV;KPA;KOE;KOB;KBU;KBL;KB;IAM;HZG;HZ;HSE;HRB;HFG;HF;HE;HAZ;GMD;GE
Z;GBB;FVT;FRM;FPL;FPK;FPI;FPA;FP;FMP;FME;FMD;FMA;FLP;FLB;FIM;FHW;FGY;FGV;FGS;FGP;FGL;FGK;FGE;FGD;FGB;FGA;FDA;FA;EZZ;EWZ;
EWS;EVT;EV;ETZ;ETL;ESZ;EPB;EP;ECM;DVL;ECR;DV;DRX;DRW;DRV;DRQ;DRK;DRF;DMD;DIF;DLP;DER;DDI;DBL;DB;DAT;D01;CPC;CIP;CHL;CE;C
AP;BVT;BVS;BVB;BV;BUG;BSV;BST;BSS;BS;BPZ;BLD;BDL;BBL;BBD;BB;BAL;BAD;ANH;AGZ;AFK;AEN;AED;AAW;AA;" == "!type:%~b=!" (
move /y "\server1\digit$\deposito\MFH3\MFH3-AFK-20150511-F01MD12340-20301231-V07-OP20-TRIFLEX-CP1_H--.pdf" "\bars
rv11\digit$\ok"
pause
)
endlocal
) )
if exist "\server1\digit$\deposito\MFH3\MFH3-AFK-20150511-F01MD12340-20301231-V07-OP20-TRIFLEX-CP1_H--.pdf" move
/y "\server1\digit$\deposito\MFH3\MFH3-AFK-20150511-F01MD12340-20301231-V07-OP20-TRIFLEX-CP1_H--.pdf" "\server1\
digit$\errori"
pause
)
1 file(s) moved.
Press any key to continue . . .

How to sort the arguments dropped to a batch file?

I am writing a batch file that finds and executes all update.bat file inside all the directories dropped onto it.
The problem here is that I expect the arguments (i.e directories' path) comes in ordered by name but it turns out they are sorted by the modified date.
Is this the default behavior of Windows (Windows 7)? Any suggestion to solve this?
Here is my batch script:
#echo off
Setlocal EnableDelayedExpansion
if [%1]==[] goto :no_update_dropped
set LOG_FILE=update_log.txt
echo You are about to run these updates:
for %%G IN (%*) do (
if exist %%~sG\NUL echo %%G
)
pause
for %%G IN (%*) do (
if exist %%G\NUL (
if exist %%G\update.bat (
call %%G\update.bat %LOG_FILE%
) else (
echo No update.bat found in %%G.
goto :no_batch_found
)
)
)
goto :success
:no_update_dropped
echo NO UPDATE FOLDER FOUND
echo Drag and drop one or more update folder to run.
goto :exit
:no_batch_found
echo UPDATE NOT COMPLETED!
goto exit
:success
echo all updated has been run successfully
goto :exit
:exit
pause
Best Regards.
You can sort your argument list right in your for loop like this:
setlocal enabledelayedexpansion
for /f "delims=" %%a in ('(for %%i in (%*^) do #echo %%~i^)^|sort') do (
set dirname=%%a
set dirname=!dirname:~0,-1!
echo use "!dirname!" without the trailing space
)
P.S. It seems like sort appends a space to the end of string,(WTF ????) so you'll have to get rid of it. I changed the code.
Finally with the help of dbenham's explanation this becomes:
for /f "delims=" %%a in ('cmd /c "for %%i in (%*) do #echo %%~i"^|sort') do (
echo use "%%a"
)
P.P.S This should work safer with commas in names (of course, they must be quoted)
for /f "delims=" %%a in ('cmd /c ^"for %%i in ^(%*^) do #echo %%~i^"^|sort') do (
echo use "%%a"
)
I would change the input set.
You can order by name by using /on and to get directories
/ad
so all directories by name =
dir /ad /on

Resources