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