tl;dr
# Note the nested quoting. CAVEAT: May break in the future.
robocopy.exe | find.exe '"Started"'
# Alternative. CAVEAT: doesn't support *variable references* after --%
robocopy.exe | find.exe --% "Started"
# *If available*, use PowerShell's equivalent of an external program.
# In lieu of `findstr.exe`, you can use Select-String (whose built-in alias is scs):
# Note: Outputs are *objects* describing the matching lines.
# To get just the lines, pipe to | % ToString
# or - in PowerShell 7+ _ use -Raw
robocopy.exe | sls Started
For an explanation, read on.
PowerShell does support piping to and from external programs.
The problem here is one of parameter parsing and passing: find.exe
has the curious requirement that its search term must be enclosed in literal double quotes.
In cmd.exe
, simple double-quoting is sufficient: find.exe "Started"
By contrast, PowerShell by default pre-parses parameters before passing them on and strips enclosing quotes if the verbatim argument value doesn't contain spaces, so that find.exe
sees only Started
, without the double quotes, resulting in an error.
There are three ways to solve this:
PS v3+ (only an option if your parameters are only literals and/or environment variables): --%
, the stop-parsing symbol, tells PowerShell to pass the rest of the command line as-is to the target program (reference environment variables, if any, cmd-style (%<var>%
)):
robocopy.exe | find.exe --% "Started"
PS v2 too, or if you need to use PowerShell variables in the parameters: apply an outer layer of PowerShell quoting (PowerShell will strip the single quotes and pass the contents of the string as-is to find.exe
, with enclosing double quotes intact):
robocopy.exe | find.exe '"Started"'
- Caveat: It is only due to broken behavior that this technique works. If this behavior gets fixed (the fix may require opt-in), the above won't work anymore, because PowerShell would then pass
""Started""
behind the scenes, which breaks the call - see this answer for more information.
If an analogous PowerShell command is available, use it, which avoids all quoting problems. In this case, the Select-String
cmdlet, PowerShell's more powershell analog to findstr.exe
can be used, as shown above.