Setting a string value to a variable - batch-file

I need to set a variable to a substring I get from a find command, but it is returning the command
findstr /is "CouId:" C:\dev\AssayInfo.txt
set number=findstr /is "CouId:" C:\dev\AssayInfo.txt
echo %number%
pause
This is what the file that I'm using findstr looks like:
Protocol: NVD_RCP_Fluidic_Accuracy_v0.4
ProtocolVersion: 1
SampleId: FLQC+20191126+00111280+96
InstrumentId: 123456789001
CouId: 138527011
CouSlot: 1
The variable should have the value 138527011 in this case.

Here you go:
#echo off
for /f "tokens=1,* delims=: " %%i in ('type "C:\dev\AssayInfo.txt" ^| findstr /i CouID') do set "number=%%j"
echo %number%
:# Here you can add your if statements etc.
pause
Note, that this is exactly what you required, as per this question and not the other question and therefore this is all I can give you now.
However, this is not even needed, you can do it without the set variable:
#echo off
for /f "tokens=1,* delims=: " %%i in ('type "C:\dev\AssayInfo.txt" ^| findstr /i CouID') do (
echo %%i
:# Here you can add your if statements etc.
)
pause

Personally, I would use:
#echo off
for /F "tokens=2" %%A IN ('findstr /ibc:"CouId: " C:\dev\AssayInfo.txt') do set "num=%%A"
rem Do some code here:
pause
exit /b 0
which is much shorter.
Note that direct comparisons can be done directly inside the for loop like:
#echo off
setlocal EnableDelayedExpansion
for /F "tokens=2" %%A IN ('findstr /ibc:"CouId: " C:\dev\AssayInfo.txt') do (
set "num=%%A"
rem Do sum comparisons with '!num!', not '%num%'!:
)
pause
exit /b %errorlevel%

Related

findstr "^" doesn't work but "^^" does to lookup the beginning lines

My findstr /c:"^string" works in funny way.
To lookup top of each lines using findstr /r with "^", is there any way to put the same query? At least, I found where there's variable as file name, /c:"^^abc" picks up properly, but /c:"^abc" doesn't.
>type test.txt
abc
abc
>type test.bat
setlocal enabledelayedexpansion
set Myfile=test.txt
for /F "usebackq delims=" %%i in (`findstr /n /r /i /c:"^abc" "!Myfile!"`) do (
echo %%i
)
goto :eof
>test.bat
1: abc
2:abc
>
Only when I put 2 "^"s, i.e /c:"^^abc", then,
...
for /F "usebackq delims=" %%i in (`findstr /n /r /i /c:"^^abc" "!Myfile!"`) do (
...
>test.bat
2:abc
>
Or, when I put %Myfile% instead of !Myfile!, it looks working with c:"^abc". But, Myfile will vary through each run. So %variable%, or immediate_value won't work for me.
Is there any ways to put a Universal lookup (any switch available?) so that I don't need to check each time I write codes? This would reduce quite a lot of time to debug.
FYI, Replacing !Myfile! with %%x by putting one more "For" loop works with Single "^". This is the only way I can forget about "^^"against !Myfile! for now.
>type test2.bat
setlocal enabledelayedexpansion
set Myfile=test.txt
for /F "usebackq delims=" %%h in (`dir /a-d /b "!Myfile!"`) do (
for /F "usebackq delims=" %%i in (`findstr /n /r /i /c:"^abc" "%%h"`) do (
echo %%i
)
)
goto :eof
>test2.bat
2:abc
>

Scheduled batch file error (0xff) - Executing normal it work fine

I've this batch file to execute.
#echo off
set /a count=0
for /f "tokens=1delims=:" %%i in ('findstr /n "^" "foto1.txt"') do set /a count=%%i
set /a rd=%random%%%count
if %rd% equ 0 (set "skip=") else set "skip=skip=%rd%"
set "found="
for /f "%skip%tokens=1*delims=:" %%i in ('findstr /n "^" "foto1.txt"') do if not defined found set "found=%%i"&set "var=%%j"
echo.%var%
break > urlfoto1.txt
echo %var% >> urlfoto1.txt
set /a count=0
for /f "tokens=1delims=:" %%i in ('findstr /n "^" "foto2.txt"') do set /a count=%%i
set /a rd=%random%%%count
if %rd% equ 0 (set "skip=") else set "skip=skip=%rd%"
set "found="
for /f "%skip%tokens=1*delims=:" %%i in ('findstr /n "^" "foto2.txt"') do if not defined found set "found=%%i"&set "var=%%j"
echo.%var%
break > urlfoto2.txt
echo %var% >> urlfoto2.txt
set /a count=0
for /f "tokens=1delims=:" %%i in ('findstr /n "^" "foto3.txt"') do set /a count=%%i
set /a rd=%random%%%count
if %rd% equ 0 (set "skip=") else set "skip=skip=%rd%"
set "found="
for /f "%skip%tokens=1*delims=:" %%i in ('findstr /n "^" "foto3.txt"') do if not defined found set "found=%%i"&set "var=%%j"
echo.%var%
break > urlfoto3.txt
echo %var% >> urlfoto3.txt
This script is generating random jpg url from a list on a file and create a txt new file with 1 random jpg url.
When I exectute it manually, it work fine.
But when I go to scheduling it with Windows Task Scheduler I retrieve a (0xFF) ERROR.
What does (0xff) mean? And why the scheduling is not working?
And similarly to LotPings answer:
#Echo Off
CD /D "%~dp0"
For %%A In (1 2 3) Do Call :Sub "%%A"
Pause
GoTo :EOF
:Sub
For /F "Delims==" %%A In ('Set line[ 2^>Nul') Do Set "%%A="
Set "total="&Set "randlinenum="
For /F "Tokens=1*Delims=[]" %%A In ('Find /V /N ""^<"foto%~1.txt"'
)Do Set "line[%%A]=%%B"&Set "total=%%A"
Set /A randlinenum=1+(%RANDOM% %% total)
SetLocal EnableDelayedExpansion
Echo(!line[%randlinenum%]!
(Echo(!line[%randlinenum%]!)>"urlfoto%~1.txt"
EndLocal
Exit /B
Please note that the Find /V /N "", (or FindStr /N "^"), construct will also include any empty lines, so if those exist in any of your foto* files this could feasibly randomly select and output an empty line.
I don't like the redundancy in your batch, use a counting for /l and a call :sub
using a find /c is simpler to get the line count of a file.
using more +x avoids the need to differentiate the skip count.
when outputting only one line, directly use > to overwrite previous content.
Here using %~dp0 (batch folder) for input/output.
:: Q:\Test\2019\05\02\SO_55951454.cmd
#echo off
cd /d "%~dp0"
for /L %%L in (1,1,3) do Call :Sub %%L
Goto :Eof
:Sub
for /f %%i in ('find /C /V "" ^<"foto%1.txt"') do set count=%%i
set /a "rd=%random% %% count"
for /f "delims=" %%i in ('more +%rd% "foto%1.txt"') do set "var=%%i"&goto :cont
:cont
echo.%var%
>"urlfoto%1.txt" echo.%var%
Goto :Eof

Assign the result of a command to a variable (batch file)

I want to store the result of a command in a variable in a for loop in a batch script. I want to loop through a series of .sql files, count how many lines each file consists of and sum up the line counts.
Here is my attempt so far:
#echo off
setlocal ENABLEDELAYEDEXPANSION
set /a count=0
set /a t=0
for /f %%a in ('dir /b *.sql') do (
#echo %%a <- THIS PRINTS THE FILE NAME
#set t=findstr /r /n "^" %%a | find /C ":" <- THIS IS INCORRECT
echo %t% <- I WANT TO PRINT THE LINE COUNT FOR THE FILE
#set /a count+=%t% <- INCREASE THE COUNTER
)
echo %count% <- PRINT TOTAL LINE COUNT
When I run
findstr /r /n "^" *.sql | find /C ":"
in a command window it works, and I know I could use that for the end objective, but this question is about the variable assignment.
Where is my mistake? The variable t is assigned the value 0 all the time.
UPDATE: (Still not working)
#echo off
setlocal ENABLEDELAYEDEXPANSION
set /a count=0
set /a t=0
for /f %%a in ('dir /b *.sql') do (
#echo %%a
for /L %%b in ('findstr /r /n "^" %%a ^| find /C ":"') do (
set /a count+=%%b
)
)
echo !count!
For anyone interested reading this later, here is the final (working version):
#ECHO off
SETLOCAL ENABLEDELAYEDEXPANSION
SET /a count=0
SET /a t=0
for /f %%a in ('dir /b *.sql') do (
#echo %%a
for /f %%b in ('findstr /r /n "^" %%a ^| find /C ":"') do (
set t=%%b
)
ECHO !t!
#SET /a count+=!t!
)
ECHO "Total:" !count!
#set t=findstr /r /n "^" %%a | find /C ":" <- THIS IS INCORRECT
doesn't work. It sets the variable t to the string findstr /r /n "^" %%a and filters the Output of the set command (which Outputs nothing) with | find /C ":", which Counts exactly Zero colons in nothing.
The best way of doing it, is:
for /f %%x in ('findstr /r /n "^" %%a ^| find /C ":"') do set t=%%x
Edit I was so focussed on repairing your code, that I didn't really realize, that you just want to count all lines of all *.SQL files. That's quite easy. No need for delayed expansion:
set count=0
for /f %%a in ('type *.sql 2^>nul ^| find /n /v ""') do set /a count+=1
echo %count%
2>nul prevents type to print the file names to the screen.
Edit2
my solution with 203 files, 47763 lines in total needs about 24 seconds. Aschipfl's edit2 solution about seven milliseconds. Impressive... find /c must have a really efficient method to count the lines.
My slightly changed code to use this capability:
set count=0
for /f %%a in ('type *.sql 2^>nul ^| find /c /n /v ""') do set /a count+=%%a
echo %count%
which also needs about 7ms. No big surprise, as it's basically the same code as Aschipfl's - just formatted differently.
There is no need to use findstr /N /R "^" to precede each line with line number and : and count the number of lines containing : afterwards.
To count the number of lines a text file contains, you only need to redirect it into find /C /V "", like this:
< "\path\to\file.txt" find /C /V ""
To use this within your for loop, you could do this:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
set /A COUNT=0
set /A T=0
for /F "eol=| delims=" %%A in ('dir /B "*.sql"') do (
setlocal DisableDelayedExpansion
echo(%%~A
for /F %%B in ('^< "%%~A" find /C /V ""') do (
endlocal
set /A T=%%B
)
echo(!T!
set /A COUNT+=T
)
echo Total: %COUNT%
endlocal
exit /B
The toggling of delayed expansion is done to avoid trouble with exclamation marks ! in any of the *.sql file names, which would be ignored otherwise and the error message The system cannot find the file specified. would appear. Delayed expansion is only required because of the (debug) line echo(!T!; if you remove that, you can disable delayed expansion for the entire script.
Edit #1:
Here is a compacted variant of the above script, without any temporary variable T and with delayed expansion disabled:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set /A COUNT=0
for /F "eol=| delims=" %%A in ('dir /B "*.sql"') do (
for /F %%B in ('^< "%%~A" find /C /V ""') do (
echo(%%~A: %%B
set /A COUNT+=%%B
)
)
echo TOTAL: %COUNT%
endlocal
exit /B
And here is a script that uses a single for /F loop to retrieve the number of lines, which lets find search for the *.sql files like find /C /V "" "*.sql", then takes its output that looks like ---------- file.sql: 5 for instance, splits off the count after : and sums up all of them. This approach needs delayed expansion again:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set /A COUNT=0
for /F "eol=| delims=" %%A in ('find /C /V "" "*.sql"') do (
set "LINE=%%~A"
echo(%%~A
setlocal EnableDelayedExpansion
set /A T=!LINE:*: =!
for /F "delims=" %%B in ("!T!") do (endlocal & set /A COUNT+=%%B)
)
echo TOTAL: %COUNT%
endlocal
exit /B
Yes, there is a second for /F loop nested as well, but this is required for transferring the value of T over the endlocal barrier.
Edit #2:
Here is probably the best solution for determining the total number of lines over multiple files. This lets type output every line of all the *.sql files, which are then counted by find. Therefore the for /F loop iterates once only, so the overall performance of this script is quite great:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set /A COUNT=0
for /F "delims=" %%A in ('
2^>nul type "*.sql" ^| find /C /V ""
') do (
set /A COUNT+=%%A
)
echo TOTAL: %COUNT%
endlocal
exit /B

how to skip comment lines to read from text file using batch script

I have a input.txt file which is having below format.
//schedulers,scott,schedule
developers,obu,develop
//testers,welcome, test
My requirement is to read the line which is not starts with symbol // using batch script.Here there is only one line which is not starts with symbol // . After reading that line need to tokenize with symbol , and set each token to a var.
I tried this batch script which is not working.
for /F "tokens=1,2,3" %%i in (input.txt) do call :process %%i %%j %%k
:process
set var1=%1
set var2=%2
set var3=%3
will any one help on this.
thanks
for /F "tokens=1,2,3" %%i in ('findstr /v /c:"//" .\InputFiles\input.txt') do call :Start %%i %%j %%k
:Start
set firsr=%1
set second=%2
set third=%3
Then these values can be used any where in the script.
See the EOF option (goes with token) you can only use single backslash.
for /F "tokens=1,2,3 EOF=\" %%i in (input.txt) do call :process %%i %%j %%k
Else
for /F "tokens=1,2,3" %%i in ('findstr /v /c:"\\" input.txt') do call :process %%i %%j %%k
#echo off
for /f "tokens=1-3" %%a in ('findstr /V "\/\/" "input.txt"') do (call:process %%a %%b %%c)
exit/b
:process
set "$var1=%1"
set "$var2=%2"
set "$var3=%3"
echo Var1 [%$var1%]
echo Var2 [%$var2%]
echo Var3 [%$var3%]

I want to find the word and replace the 3 word after the search string with my desired word in batch script

#ECHO OFF
#setlocal enabledelayedexpansion
SET InFile=test.txt
FOR /F "tokens=*" %%A IN ('FINDSTR "wordA" "%InFile%" ^| FINDSTR "wordB"') DO CALL :FindString "%%A"
pause
:FindString
SET String=%~1
SET String=%String:*wordA =%
SET String=%String: wordB=`%
FOR /F "tokens=1 delims=`" %%A IN ('%String%') DO ECHO %%A
Here I just written a code to replace the word with my desired character
When I am running these code I am getting the error saying
. was unexpected at this time
You were close. See mods to your code below. If you really want the first word after wordB... this will do it.
Don't enable delayed expansion if you don't need it because that just messes you up if there are ! in the text.
#echo off
SET InFile=test.txt
FOR /F "tokens=*" %%A IN ('FINDSTR "wordA" "%InFile%" ^| FINDSTR "wordB"') DO CALL :FindString "%%A"
pause
goto :eof
:FindString
SET String=%~1
SET String=%String:*wordA =%
SET String=%String:wordB =%
FOR /F "tokens=1" %%A IN ('echo.%String%') DO ECHO.%%A
:goto :eof
I'm not sure, what you want, but you can try this:
#echo off &setlocal
SET "InFile=test.txt"
echo(wordA wordB>"%InFile%"
FOR /F "tokens=*" %%A IN ('FINDSTR "wordA" "%InFile%" ^| FINDSTR "wordB"') DO CALL :FindString "%%A"
pause
goto:eof
:FindString
SET "String=%~1"
SET "String=%String:*wordA =%"
SET "String=%String: wordB=`%"
FOR /F "tokens=1 delims=`" %%A IN ("%String%") DO ECHO %%A

Resources