Search code examples
windowsbatch-filefindstr

How can find exact match with findstr in for of windows batch


What the only thing I want to do is in a windows batch, to get output of a dir command with findstr.

If I knew this was the most complicated thing in life, I wouldn't try.

What I did is, first, write my command that I need its output:

dir /A D:\path | findstr mykeyword

But actually I need exact match of "keyword", so I found this:

https://stackoverflow.com/a/39235594/2536614

So, my command is now:

dir /A D:\path | findstr "\<mykeyword\>"

I have tried it and the output is what I want.

Then, how do I get its output in a batch file? Of course, the intuitive tries don't work. It must be complicated. So, I found this:

https://stackoverflow.com/a/10131068/2536614

A loop just to set a variable. Anyway, this brings another complication. Now I can not write "\<mykeyword\>" correctly, escaping the special characters, within, first ' then ", in For command, as the anwser suggests.

I have tried this:

For /F %%A in ('"dir /A %path_to_look% | findstr ""\\^<mykeyword\\^>"""') do set res1=%%A

This returns nothing. res1 is empty.

So, how can I find exact match with findstr, but within For command?


Solution

  • Yes, to capture the output of the command line:

    dir /A %path_to_look% | findstr "\<mykeyword\>"
    

    by a for /F loop, you could use (note the escaped pipe ^| which is necessary as it is exposed to the command processor unquoted):

    for /F %%A in ('dir /A %path_to_look% ^| findstr "\<mykeyword\>"') do set res1=%%A
    

    or (with additional surrounding quotes, leading to the pipe to appear quoted but to the redirection symbols < and > unquoted, hence requiring escaping):

    for /F %%A in ('"dir /A %path_to_look% | findstr "\^<mykeyword\^>""') do set res1=%%A
    

    Knowing that for /F executes the given command by cmd /C and regarding its rules for handling of quotes (type cmd /? and read the usage text) may help to understand why this works too.

    You may have noticed that the second method inverses the quotation status of the whole command line, but this can be avoided by escaping the outer-most quotes:

    for /F %%A in ('^"dir /A %path_to_look% ^| findstr "\<mykeyword\>"^"') do set res1=%%A
    

    However, let me recommend to use this only in case the outer-most quotes are really necessary in order to avoid syntax errors in a few unusual situations.


    However, there are several issues in the command line (let us stick to the first approach here), which I want to depict here:

    • the (unknown) path is unquoted, which could lead to issues with some special characters, so better use "%path_to_look%" (assuming that the variable does not already contain the quotes itself, which would not be advicable);
    • dir, without its /B switch, returns more than just the file names (like dates/times, file sizes, and a header and footer), which you probably do not really care about, hence provide /B;
    • dir /A specifies to list all items (likes files, directories, reparse points, even hidden and system items), though you are probably only interested in (unhidden and non-system) files, hence you perhaps want to use /A:-D-H-S instead;
    • file names may also include white-spaces, hence you should specify the for /F option delims=; file names may theoretically also start with ;, so eol=| might make sense (as | cannot occur in file names);
    • file names are case-insensitive, and so should be the keyword search by adding /I to findstr;
    • you should use the quoted set syntax in order to protect special characters;

    All this leads to the following improved command line:

    for /F "delims= eol=|" %%A in ('dir /B /A:-D-H-S "%path_to_look%" ^| findstr /I "\<mykeyword\>"') do set "res1=%%A"