Page 1 of 1

Finding two backslashes

Posted: 30 Mar 2015 13:13
by Squashman
Not sure why I can't figure this out. Just trying to find all files that use UNC paths in them. So I figured I would just search for a double back slash. But every time I try it outputs all of my files. There should only be a handful. But don't feel like manually searching through dozens of files.

I have tried
findstr /M "\\" *.*
findstr /M "\\\\" *.*
findstr /M /R "\\\\" *.*

Re: Finding two backslashes

Posted: 30 Mar 2015 13:31
by ShadowThief
What about the /L flag? Windows can interpret C:\path\\to\\file\\name as valid syntax, so something might be getting lost in there (I don't have any network drives so I can't test this).

Re: Finding two backslashes

Posted: 30 Mar 2015 13:37
by Squashman
Tried the literal switch as well. Trying to read up on Dave's extensive documentation. I must not be understanding something.

Re: Finding two backslashes

Posted: 30 Mar 2015 13:43
by Squashman
Assuming I ALWAYS put quotes around my file paths as a best practice, this seems to work but would rather just look for \\.
findstr /M /C:"\"\\\\" *.*

Re: Finding two backslashes

Posted: 30 Mar 2015 13:48
by Squashman
I literally need to use Dave's examples as he provided them. Don't put quotes around your search string!!!!!!
C:\BatchFiles\backslashes>findstr \\\\ *.*
TwoSlashes.txt:TwoSlashes\\TwoSlashes
TwoSlashes.txt: \\TwoSlashes
TwoSlashes.txt: "\\TwoSlashes"

C:\BatchFiles\backslashes>findstr \\\ *.*
TwoSlashes.txt:TwoSlashes\\TwoSlashes
TwoSlashes.txt: \\TwoSlashes
TwoSlashes.txt: "\\TwoSlashes"

Re: Finding two backslashes

Posted: 30 Mar 2015 15:18
by dbenham
The backslash and quote escape rules are really wonky.

I can usually get it to work with enough patience and experimentation, but I don't think I've figured out the exact rules yet. I'm also pretty sure it changes between versions (especially Vista).

I find the simplest reliable method that seems to work in all situations is to use the regular expression [\\] to represent a single backslash. It works both quoted and unquoted.

Code: Select all

findstr "[\\][\\]" *.*
findstr [\\][\\] *.*


Dave Benham

Re: Finding two backslashes

Posted: 30 Mar 2015 19:55
by penpen
I think (if i remember right.... tested some long long while ago using XP) this happens:
A doublequote character toggles an additional expansion phase (:= "doublequote expansion phase") between "on" and "off",
seperating the search string in "doublequoted" and "not doublequoted" parts.
Initially the state of this phase is "off".

Categorizing the doublequotes to:
- opening doublequote := a doublequote that toggles this state to "on".
- closing doublequote := a doublequote that toggles this state to "off".
- literal doublequote := a doublequote that does not toggle this state.

A doublequote following a "closing" doublequote or a '\' is a literal doublequote:

Code: Select all

"doublequoted"not_doublequoted"doublequoted"not_doublequoted
"doublequoted"""doublequoted"not_doublequoted
"doublequoted\"doublequoted"not_doublequoted
Note: A space in the 'not doublequoted' part ends the search string.
I haven't tested, if there are other characters that terminates the search string.

The opening and closing doublequotes are removed.
If a '\' follows a first '\', then the first '\' is removed (if it is not within a class block []), else it stays as is.

Code: Select all

"\"" --> \"
"\"  --> \
"\\"  --> \
"a\"  --> a\
"a\b" --> a\b
Note: You may also 'escape' the doublequotes by using """.

Search strings using this notation are defaulted to regular expressions (separated by space characters):

Code: Select all

findstr "three regular expressions" file.txt

Search strings using this notation are defaultet to literally expressions (separated by space characters):

Code: Select all

findstr /C:"one literal expression"


Examples for this "doublequote expansion":

Code: Select all

search string  --> matching pattern (interpreted "literally", or as a regular expresssion)
"\a"           --> \a
"\""           --> \"
"\\"           --> \
"\\\\"         --> \\
"\\\\\\"       --> \\\
"\\\\\\\\"     --> \\\\
"[\\][\\]"     --> [\\][\\]
"[\\\\][\\\\]" --> [\\\\][\\\\]
               ...
"\."           --> \.
"\*"           --> \*
"\^"           --> \^
"\$"           --> \$
"\["           --> \[
"\]"           --> \]
"\<"           --> \<
"\>"           --> \>


penpen

Re: Finding two backslashes

Posted: 30 Mar 2015 21:11
by dbenham
Wouldn't it be nice if FINDSTR were that logical, but alas, no. :evil:

For example "\\\\" will match a single \ :!: (I haven't figured this one out). But remove the quotes, and it works as expected:

Code: Select all

C:\>echo \|findstr "\\\\"
\

C:\>echo \|findstr \\\\

C:\test>


Dave Benham

Re: Finding two backslashes

Posted: 31 Mar 2015 07:28
by Squashman
dbenham wrote:Wouldn't it be nice if FINDSTR were that logical, but alas, no. :evil:
We probably can't blame this one on Bill's peyote smoking either. He was probably well removed from that development by the time the findstr command came around.

Re: Finding two backslashes

Posted: 31 Mar 2015 07:43
by dbenham
Here is the story behind FINDSTR, as told by Raymond Chen - a long time developer at MicroSoft
http://blogs.msdn.com/b/oldnewthing/arc ... 72436.aspx


Dave Benham

Re: Finding two backslashes

Posted: 31 Mar 2015 08:25
by Squashman
Strange that they first called it QGREP. I guess you could say it is like GREP but IMHO, GREP is a lot more powerful then FINDSTR. But, luckily we have JREPL now. :wink:

Re: Finding two backslashes

Posted: 31 Mar 2015 14:30
by penpen
dbenham wrote:Wouldn't it be nice if FINDSTR were that logical, but alas, no. :evil:

For example "\\\\" will match a single \ :!: (I haven't figured this one out). But remove the quotes, and it works as expected:

Code: Select all

C:\>echo \|findstr "\\\\"
\

C:\>echo \|findstr \\\\

C:\test>


Dave Benham
Didn't i say this?
penpen wrote:

Code: Select all

search string  --> matching pattern (interpreted "literally", or as a regular expresssion)
: ...
"\\\\"         --> \\


With this notation i wanted to say:

Code: Select all

:: this command
findstr /L /C:"\\\\" test.txt
:: equals that command:
findstr /L /C:\\ test.txt

::same for all other in that list
findstr /L /C:"\\\\\\\\" test.txt
findstr /L /C:\\\\ test.txt

:: ...


penpen