0

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?

Mert Mertce
  • 1,049
  • 7
  • 34
  • 1
    As your question currently stands, I'm not sure why you'd need to use `findstr.exe` at all. Are you trying to match an exact file name? and if so what about _(`dir "%pathtolook%\mykeyword" /A:-D /B`, or `dir "%pathtolook%\mykeyword *" /A:-D /B` or `If Exist "%pathtolook%\mykeyword"` or `If Exist "%pathtolook%\mykeyword *"`)_, or are you trying to find an exact directory name? _(`dir "%pathtolook%\mykeyword" /A:D /B` or `dir "%pathtolook%\mykeyword *" /A:D /B` or `If Exist "%pathtolook%\mykeyword\*"` etc.)_. **An unfocused question will not attract focused answers!** – Compo Feb 02 '22 at 19:22
  • @Compo, ok, actually what I am looking for is, if there is a directory with a specific name, and if there is, if it is a symbolic link or not. But I was afraid asking "how to find if dir is symbolic or not", since in other answers I see 32546238462387 lines of batch code just to find that! So, I begun to try something like DIR .. | findstr "SYMLINKD". Then I came up with this. I couldn't imagine that it was so complicated to ask windows if a directory is symlink or not. – Mert Mertce Feb 02 '22 at 19:36
  • Did you not read the usage information for the `dir` command, at the Command Prompt, i.e. `dir /?`. There is an option specifically for 'reparse points' Examples: `Dir "%pathtolook%\*mykeyword" /A:DL /B | %SystemRoot%\System32\findstr.exe /ILXC:"mykeyword"`, or `Dir "%pathtolook%\mykeyword*" /A:DL /B | %SystemRoot%\System32\findstr.exe /ILX "mykeyword"`. – Compo Feb 02 '22 at 19:52
  • @Compo The problem begins when I want to use the output of this command with a variable. Please see my question. – Mert Mertce Feb 02 '22 at 19:56
  • 1
    You don't need the _additional_ quotes in the commands inside a FOR /F. Try: `For /F %%A in ('dir /A %path_to_look% ^| findstr "\"') do set res1=%%A` – Aacini Feb 02 '22 at 20:33
  • @Aacini I wish you read the question a couple hours ago :) This was just the answer! Thanks! – Mert Mertce Feb 02 '22 at 20:51
  • @MertMertce you essentially were on the right path to get the answer yourself. Why you chose to use so many extra sets of quotes and escaping with the findstr character "\" and escaping with the cmd.exe character "^" was your main problem. Where did you even find a remotely similar usage of a `FINDSTR` expression on the Internet like that. Always keep in mind the [KISS PRINCIPLE](https://en.wikipedia.org/wiki/KISS_principle) – Squashman Feb 02 '22 at 20:57
  • @Squashman you're right. In the question I have given the links from where I got those, evil in('" etc. I was wondering why a human needs to do ' and also " there. But it took me much time to find out ^|. – Mert Mertce Feb 02 '22 at 22:01

2 Answers2

2

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"
aschipfl
  • 33,626
  • 12
  • 54
  • 99
0

My solution has been using ^| instead of | only.

This makes it possible to use only ' instead of '" inside in().

So now I could write findstr "" without need of escaping " character, which was the only thing I was trying to find.

So,

before:

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

Supposedly " could be escaped as "" but this code did not work.

So,

after:

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

This does work.

(Though, in other words "how can escape special characters when using findstr within in ('""') question remains as a mystery.)

aschipfl
  • 33,626
  • 12
  • 54
  • 99
Mert Mertce
  • 1,049
  • 7
  • 34
  • 1
    `For /F %%A in ('dir /A %path_to_look% ^| findstr "\"') do set res1=%%A` could be rewritten as `for /F %%A in ('"dir /A %path_to_look% | findstr "\^""') do set res1=%%A`, though I would not recommend that… – aschipfl Feb 03 '22 at 13:35
  • @aschipfl Thank you! It is so good to know also this! I was wondering how I could write it this way. It does not matter if it is recommended way or not! In another ocasion I could need. Actually, this is the exact answer of the question. My answer is "another way" to do it. – Mert Mertce Feb 03 '22 at 14:58