Findstr command in for-loop stops after a certain line - windows

I have this snippet of script:
for /F "tokens=1* delims=:" %%a in ('findstr /N /C:"%SECTION%" /C:"%TARGET%" %BASE%') do (
:: Stuff:
)
echo Search Parameters not found
...where SECTION and TARGET are two search parameters. The BASE file is approximately 16,000 lines.
Here's my problem:
When I execute the for-loop inside a batch script, it searches for 2397 lines exactly, then just gives up. However, if I run the findstr command manually, it will search all lines as expected.
Any ideas?

Does this fail for you? It works here in Win 8 and a XP Pro VM to print 16,000 lines.
#echo off
(for /l %%a in (1,1,16000) do #echo 0123456789012345678901234567890123456789)>file
SET "section=123"
SET "target=456"
SET "base=file"
ECHO start
for /F "tokens=1* delims=:" %%a in ('findstr /NC:"%SECTION%" /C:"%TARGET%" "%BASE%"') do (
ECHO %%a
)
pause

Fool's mistake - upon changes of versions, the location of a certain file shifted. So while I thought my search for the file was correct, it actually ended up retrieving a file in similar name, but not the same file (MotionBase.class.asasm vs what I needed: BASE.class.asasm)
Thought I checked the location before submitting this question, but apparently not.

Related

Output all results of findstr to seperate txt files

Currently my code is: findstr Starfy ./List.txt > result.txt
My result.txt is
3841 - Legendary Starfy, The (USA).zip
x166 - Legendary Starfy, The (USA) (Demo) (Kiosk).zip
However, I want result 1 and result 2 to have their own seperate files, so it would look like:
result1.txt > 3841 - Legendary Starfy, The (USA).zip
result2.txt > x166 - Legendary Starfy, The (USA) (Demo) (Kiosk).zip
I'm unsure how to make this work, and would love if someone is able to help point me in the right direction.
This works:
#echo off
for /F "tokens=1* delims=:" %%a in ('findstr "Starfy" .\List.txt ^| findstr /N "^"') do >result%%a.txt echo %%b
Just pass your original results into another instance of findstr /N command that add line numbers. After that, separate the number and the line in a for /F command and output each line to its corresponding numbered file...
for /f "tokens=1,* delims=:" %%S in ('findstr /i "echo" "%~f0"^|findstr /n /i "echo" ') do ECHO %%T>"U:\moreresults\result%%S.txt"
The command quoted in parentheses finds a string (in this case, echo) ignoring case (/i) within the file "%~f0" (this batch file, which contains a heap of standard code I use for testing). This is passed to another instance of findstr, this time looking for the same string, but numbering the lines (as serialnumber:linetext).
The resultant text is tokenised using : as a separator, so %%S receives the serialnumber and %%T receives the rest of the line (token *). Then simply build the result filename using %%S and write the text part of the line to it.
The caret is used to escape the pipe so that cmd knows that the pipe is part of the command-to-be-executed, not of the for command.
Assuming that you do not already have files in the location you're outputting your results, which could alalready be named using that intended naming scheme, then something like this may suit you:
#Echo Off
SetLocal EnableExtensions EnableDelayedExpansion
Set "i=0"
For /F Delims^=^ EOL^= %%G In (
'%SystemRoot%\System32\find.exe /I "Starfy" 0^<".\List.txt" 2^>NUL'
) Do (
Set /A i += 1
1>"Result!i!.txt" Echo %%G
)
Please note that I used find.exe instead of findstr.exe simply because your example used a simple string containing a series of alphabetic only characters. Feel free to change it to '%SystemRoot%\System32\findstr.exe /LIC:"Starfy" ".\List.txt" 2^>NUL', or similar, should you require a more specialized matching mechanism.

For loop and delims in batch files

Can someone please help me understand command file syntax
IF "%INPUT_PATH%"=="" (
echo Searching for latest test results in: %TEST_RESULTS%
FOR /F "delims=" %%i in ('dir /O-D /B "%TEST_RESULTS%\*.trx"') DO (
SET INPUT_PATH=%TEST_RESULTS%\%%~ni
GOTO :DoneInputPath
) )
I get that it first checks if INPUT_PATH variable is empty and if it is empty then enters into an inner for loop, I am lost otherwise
specifically
FOR /F "delims=" %%i in ('dir /O-D /B "%TEST_RESULTS%\*.trx"')
SET INPUT_PATH=%TEST_RESULTS%\%%~ni
Most of the information you need is available in the built-in help, though it can be daunting if you are new to batch programming. For example, type HELP FOR or FOR /? from the command prompt to get help on the FOR command.
Explanation:
FOR /F "delims=" %%i in ('dir /O-D /B "%TEST_RESULTS%\*.trx"') ...
The DIR command lists all of the *.TRX files within the %TEST_RESULTS% path. The /B option gives the brief format (file names only). The /O-D option sorts the files by last modified date descending (newest first).
The FOR /F command has three modes, depending on the format of the IN() clause. The fact that the IN() clause is enclosed in single quotes means that FOR /F treats the contents as a command, and processes the output of the command, one line at a time. The "delims=" option means do not parse into tokens (preserve each entire line). So each line is iteratively loaded into the %%i variable. The %%i variable only exists within the context of the FOR command.
SET INPUT_PATH=%TEST_RESULTS%\%%~ni
I think you know what most of this command does. The only "unusual" aspect is the %%~ni syntax. That syntax expands the value of %%i into the base file name only, without any extension.
GOTO :DoneInputPath
The GOTO causes the FOR loop to abort after the first iteration. This means that INPUT_PATH will be set to the name of the most recently modified *.trx file, since it sorted to the top.
If the GOTO were not there, then the end result would be the oldest *.trx file instead.
try this, explanation is in the comment:
IF NOT DEFINED INPUT_PATH (
echo Searching for latest test results in: %TEST_RESULTS%
REM dir /OD means older files first and the youngest last, the last remains in INPUT_PATH; use "%%~nxi" for file name + file extension
FOR /F "delims=" %%i in ('dir /OD /B "%TEST_RESULTS%\*.trx"') DO SET "INPUT_PATH=%TEST_RESULTS%\%%~ni"
)

Parsing a delimited config file using FOR on Windows

I have a java properties file to parse, it contains key value pairs of the form key=value, one on each line.
After digging around on the site, I've found this site that explains the FOR syntax, and also this question.
I constructed the following line to get the value of the backupdir.windows property in config.properties:
for /f "delims== tokens=2" %i in ('findstr backupdir.windows= config.properties') do #echo %i
The above works if you type it at the command prompt, but if I save it as a file 'test.cmd' and then execute that, I get 'i was unexpected at this time.'
Same thing happens if I change the extension to .bat (in case doing so would make it use
earlier MSDOS syntax).
What's going wrong here? I'm running Windows 7.
Better to do it like this:
#echo off
for /f "tokens=2 delims==" %%a in ('findstr /b /i "backupdir.windows" config.properties') do echo %%a
it needs to be %%i in a batch file. And just %i on the command line.

Why is the FOR /f loop in this batch script evaluating a blank line?

I'm trying to write a batch script that obtains (among other things) a list of all of the disk drives the computer has. The basic code looks something like this:
REM Build the list of disk drives to monitor
SETLOCAL enabledelayedexpansion
FOR /f "skip=1 tokens=1 delims=:" %%a in ('"WMIC logicaldisk WHERE drivetype=3 GET deviceid"') do (
SET "DISK_DATABASES=!DISK_DATABASES!%%a|"
SET "DRIVES_TO_MONITOR=!DRIVES_TO_MONITOR!%%a:\\|"
)
I pretty obviously build two lists with slightly different formats for use later. When I run this, however, the output I get looks something like this:
C|D|E||
C:\\|D:\\|E:\\|:\\|
Now, I expect the trailing pipe in both cases and I can manage that, but I'm really confused why there is an extra blank entry in there. If I run the wmic command manually, I can see that there is indeed a blank line at the end of the output, but my understanding is that /f was specifically supposed to ignore blank lines.
If I turn ECHO on, it looks like that last line is just coming in as a carriage return/newline or similar. Is there a way to do what I'm expecting? Am I missing something? I tried to write an if condition in the loop to exclude this last line, but it was... funky and never worked. I appreciate any/all help.
I just came over this topic. I've been using findstr /v to exclude empty lines:
FOR /f "usebackq skip=1 tokens=1 delims=:" %%a in (`WMIC logicaldisk WHERE "drivetype=3" GET deviceid ^| findstr /v /r "^$"`) do (
In this case the last iteration produces not an empty item, and you get your output of C|D|E|| only with echo %DISK_DATABASES%,
but echo !DISK_DATABASES! will output ||D|E|??
That's because the last element is a single <CR> character.
And <CR> characters are directly removed after the percent expansion, but not with delayed expansion.
You could avoid this, using the percent expansion to remove them
setlocal EnableDelayedExpansion
FOR /f "skip=1 tokens=1 delims=:" %%a in ('"WMIC logicaldisk WHERE drivetype=3 GET deviceid"') do (
set "item=%%a"
call :removeCR
if not "!item!"=="" (
SET "DISK_DATABASES=!DISK_DATABASES!!item!|"
SET "DRIVES_TO_MONITOR=!DRIVES_TO_MONITOR!!item!:\\|"
)
)
goto :eof
:removeCR
:removeCR
set "Item=%Item%"
exit /b
According to http://ss64.com/nt/for_f.html
Many of the newer commands and utilities (e.g. WMIC) output text files in unicode format, these cannot be read by the FOR command which expects ASCII.
To convert the file format use the TYPE command.
So it appears that WMIC and FOR don't play nice together.
I discovered a more efficient and more reliable method to strip the unwanted <CR> from the end of each line. No temp file, and no CALL needed.
I don't understand the mechanism of how FOR /F converts the WMIC unicode output into ASCII. Normally FOR /F cannot read unicode. But however it works, each converted line ends with <CR><CR><LF>. FOR /F breaks lines at each <LF>, and then if the last character in the line is <CR> it strips that last <CR>, in this case leaving behind the unwanted <CR>.
The solution is to simply pass each line through one more FOR /F :-)
#echo off
setlocal enableDelayedExpansion
for /f "skip=1 delims=" %%A in (
'wmic logicaldisk where "drivetype=3" get deviceid'
) do for /f "tokens=1 delims=:" %%B in ("%%A") do (
set "disk_databases=!disk_databases!%%B|"
set "drives_to_monitor=!drives_to_monitor!%%B:\\|"
)
This method is more reliable then using normal expansion because you don't have to worry about quoting or escaping special characters. For example, The CALL method that uses normal expansion cannot handle a string like "this & that" & the other. But this method has no problem with such a string.
Add ^| findstr . and you will get only not blank lines
REM Build the list of disk drives to monitor
SETLOCAL enabledelayedexpansion
FOR /f "skip=1 tokens=1 delims=:" %%a in (
'"WMIC logicaldisk WHERE drivetype=3 GET deviceid" ^| findstr .') do (
SET "DISK_DATABASES=!DISK_DATABASES!%%a|"
SET "DRIVES_TO_MONITOR=!DRIVES_TO_MONITOR!%%a:\|"
)
My standard idiom for dealing with this is to write the output from WMIC to a temp file, then use TYPE (which reduces UTF16 to ASCII) to feed that into FOR, like this:
:: Standard environment setup
setlocal enabledelayedexpansion
:: Every variable whose name starts with "tf" will identify a temporary
:: file - remove any such variables inherited from the parent environment
for /f %%V in ('set tf') do set %%V=
:: Create some temporary filenames. Prefix all of them with this script's
:: own name to avoid clashes with those owned by other scripts.
for /l %%I in (1,1,4) set tf%%I="%temp%\%~n0-temp%%I.txt"
:: Use temp file to work around coding mismatch between WMIC out and FOR in
wmic product where "name like 'Microsoft Office %% 2010'" get packagecache >!tf1!
for /f "skip=1" %%P in ('type !tf1!') do if exist "%%~P" msiexec /x "%%~P" /passive /norestart
:: Before quitting script, clean up temporary files
for /f %%V in ('set tf') do if exist "%%~V" del /f /q "%%~V"
endlocal
Run the following command:
wmic blah /value | find "=" >> wherever
Output will be:
field=value
Note that there will be no extra lines.

Force passing long file names to dos for command

I have problem with following simple dos command:
FOR %%f IN (.\07_PROCEDURES\DataSources\*.sql) DO echo "%%f"
It does some action for every file with sql extension. Everything works fine, except long names. When directory contains files, with sql_ extensions, they are picked up too. But this behavior depend on whether 8.3 files are turned on or off on file system. If they are turned on (default choice on most computers) sql_ are passed, because extension is cropped.
How to force for fetch long file names ? Thanks !
P.S. Do not offer powershell upgrade.
You can try to examine the extension in the loop itself
for %%f in (*.sql) do (
if /i "%%~xf" EQU ".sql" echo %%f
)
You can try something like this:
for /f "usebackq delims=" %%f in (`dir /b .\*.sql ^| findstr /r .*\.sql$`) do #echo "%%f"

Resources