The command
%SystemRoot%\System32\findstr.exe /B /R /C:"13[^0-9]" ELabs.tab
works and outputs just the line beginning with 13
and ignoring the lines beginning with 130
to 139
, 1300
to 1399
, ...
This command is used within a FOR loop as command to execute of which output to STDOUT should be captured and processed by FOR which results in implicitly running this command line in another command process in background.
But before the command line
Findstr /B /R /C:"%Begin%[^0-9]" !_RunlistName!
is executed with %SystemRoot%\System32\cmd.exe /c
in a background command process, it is twice parsed by the command process executing the batch file.
On first parsing done already before executing entire FOR command block, the environment variable reference %Begin%
is replaced by the entered number like 13
. The caret character ^
is kept on this parsing step. So before running FOR, the command line to later execute becomes for example
Findstr /B /R /C:"13[0-9]" !_RunlistName!
But because of !_RunlistName!
referencing environment variable _RunlistName
with delayed expansion, this command line is parsed once again immediately before executing the command line in another command process. And on this second parsing step ^
is interpreted as escape character and therefore removed. For that reason the background command process is started with the command line
C:\Windows\System32\cmd.exe /c Findstr /B /R /C:"13[0-9]" ELabs.tab
The lines found by FINDSTR are now not correct anymore because ^
which should mean NOT in the character class definition was before interpreted as escape character and therefore removed which changes the meaning of the regular expression.
One solution is using within FOR command line:
Findstr /B /R /C:"%Begin%[^0-9]" %_RunlistName%
By using %_RunlistName%
there is no second parsing step by command process executing the batch file and therefore the caret character is kept on running this command line later for example with
C:\Windows\System32\cmd.exe /c Findstr /B /R /C:"13[0-9]" ELabs.tab
A second solution is escaping the caret with one more caret, i.e. using
Findstr /B /R /C:"%Begin%[^^0-9]" !_RunlistName!
This results also in executing FINDSTR for example with /C:"13[^0-9]"
.
These two solutions were offered also by MC ND.
Another solution is using within FOR command line:
Findstr /B /R /C:"%Begin%\>" %_RunlistName%
\>
means end of a word as explained in help output by running findstr /?
from within a command prompt window. As the searched number must be found at beginning of a line, usage of \>
results in finding only the two lines starting with exactly the two entered numbers.
How to find out what is going on here on batch file execution?
There is the great, free Windows Sysinternals tool Process Monitor.
After downloading the ZIP file and extracting the files to any local directory like "%ProgramFiles%\Sysinternals"
with administrator privileges or "%USERPROFILE%\Desktop\Sysinternals"
with current user permissions, the executable file Procmon.exe
must be executed with Run as administrator.
On first start of this free tool offered by Microsoft it is necessary to accept the license agreement.
Then the Process Monitor Filter dialog is opened and it is advisable for the investigation of this batch file execution to add two filters:
- Process Name is cmd.exe then Include and clicking on button Add.
- Process Name is findstr.exe then Include and clicking on button Add.
Next a look on the last 5 symbols on right side of the toolbar should be made which indicate and on click toggle the state of the general display filters. The filing cabinet symbol with tooltip Show File System Activity should be enabled as the only one because getting displayed only file system activities is all needed for investigation of this batch process.
Press Ctrl+X or click on fifth symbol from left side of the toolbar to clear already made record and execute the batch file from within a command prompt window (preferred on debugging a batch file) or with a double click on the batch file.
After batch file execution finished and input focus is back on Process Monitor, press Ctrl+E or click on third symbol from left side of the toolbar to stop capturing which takes some seconds.
Now look on the record. The batch file is executed with process cmd.exe
with a specific PID (process identifier).
On scrolling down it can be seen that there is suddenly one more process cmd.exe
with a different PID. This is the background command process executed to run the FINDSTR command line.
The command line used to start this second cmd.exe
process can be seen after a secondary (right) mouse button click on the line with second cmd.exe
to open the context menu, a primary (left) mouse button click on first context menu item Properties and a primary (left) mouse button click on tab Process.
On using Findstr /B /R /C:"%Begin%[^0-9]" !_RunlistName!
in batch file and entering 13
for Begin
the command line is:
C:\Windows\system32\cmd.exe /c Findstr /B /R /C:"13[0-9]" ELabs.tab
And this makes it clear that the caret character was removed from the command line already before execution of this background command process for executing FINDSTR.
For that reason it is no surprise that the command line of process findstr.exe
is in this case:
Findstr /B /R /C:"13[0-9]" ELabs.tab
With modifying the batch file as suggested and running it each time after clearing Process Monitor log with Ctrl+X and enabling capturing again with Ctrl+E, it can be seen how the background command process for execution of the command line specified in FOR command line is really executed resulting in finally executing FINDSTR with the right parameters.
Free Process Monitor is really a great tool to find out the reason for an unexpected behavior of an application or script.