Why can "find" not be used in PowerShell?

What does find.exe find objectionable about the parameters when it is used in a PowerShell console shell?

These commands work as expected in a cmd.exe shell:

PS C:\Windows\System32\WindowsPowerShell\v1.0> find /i "System.Diagnostics.Process" *.ps1xml
FIND: Parameter format not correct
PS C:\Windows\System32\WindowsPowerShell\v1.0> find /i "System.Diagnostics.Process" *.ps1xml
FIND: Parameter format not correct
PS C:\Windows\System32\WindowsPowerShell\v1.0> C:\Windows\System32\find.exe /i "System.Diagnostics.Process" *.ps1xml
FIND: Parameter format not correct
PS C:\Windows\System32\WindowsPowerShell\v1.0> C:\Windows\System32\find.exe /i "System.Diagnostics.Process" .\DotNetTypes.format.ps1xml
FIND: Parameter format not correct

Try:

find /i "`"System.Diagnostics.Process`"" *.ps1xml

I used Sysmon.exe to compare the executions in PowerShell.exe and cmd.exe:

For cmd.exe:

 Image: C:\Windows\System32\find.exe
 CommandLine: find  /i "System.Diagnostics.Process" *.ps1xml
 ParentImage: C:\Windows\System32\cmd.exe

For PowerShell:

 Image: C:\Windows\System32\find.exe
 CommandLine: "C:\Windows\system32\find.exe" /i System.Diagnostics.Process *.ps1xml
 ParentImage: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe

we can see that in PowerShell, the quotes around the search-term are missing, so by adding another set of double-quotes it should work.


TL;DR:

Escape the double quotes or put the string inside single quotes

find.exe /i "`"System.Diagnostics.Process`"" *.ps1xml
find.exe /i """System.Diagnostics.Process""" *.ps1xml
find.exe /i '"System.Diagnostics.Process"' *.ps1xml
find.exe /i `"System.Diagnostics.Process`" *.ps1xml

or use verbatim arguments

find.exe --% "System.Diagnostics.Process" *.ps1xml

As Peter Hahndorf said, PowerShell is stripping the outer quotes. See PowerShell stripping double quotes from command line arguments. You can check it by echoing or writing the string directly in command line

PS C:\> echo C:\Windows\System32\find.exe /i "System.Diagnostics.Process" *.ps1xml
C:\Windows\System32\find.exe
/i
System.Diagnostics.Process
*.ps1xml
PS C:\> "System.Diagnostics.Process"
System.Diagnostics.Process

IMHO it's a good thing because now you can use single quotes to wrap strings. You also have a standardized way to pass special characters in parameters similar to bash, unlike in cmd where embedded double quotes are a pain

According to PowerShell quoting rule you must escape the quote by either `backticks` or the double quote itself, or simply put it in single quotes like above

In simple cases like this when there's no space in the parameter you can also escape the double quotes directly without putting it inside another pair of quotes

find.exe /i `"System.Diagnostics.Process`" *.ps1xml

However there's an easier way with Verbatim arguments --%

In PowerShell 3.0 the special marker --% is a signal to PowerShell to stop interpreting any remaining characters on the line. This can be used to call a non-PowerShell utility and pass along some quoted parameters exactly as is.

As a result you can use it like this

find.exe --% "System.Diagnostics.Process" *.ps1xml

Or if you don't need Unicode support then you can simply find with findstr which doesn't need the quotes

PS C:\Users> help | findstr command
    topics at the command line.
    The Get-Help cmdlet displays help at the command line from content in

But if PowerShell is available then you can use its Select-String cmdlet directly. It's much more powerful than find and findstr