Prepend /c:
to your search string in order to make findstr
treat it as a single string to search for:
Get-Content .\input.json | findstr /n /l /c:"\`"name\`": \`"or" # Note the /c:
Note the use of the Get-Content
cmdlet for reading a file line by line, which type
is a built-in alias for in PowerShell.
Note:
By default, if a search string contains spaces, findstr
searches for the occurrence of any of the space-separated words, i.e., "name"
or "or
, causing both lines to match. /c:
signals that the string as a whole string should be searched for (either as a regular expression, by default, or as a literal string, with /l
)
Except for the missing /c:
, your search string was correct, but you could have simplified by using a verbatim (single-quoted) string ('...'
):
... | findstr /n /l /c:'\"name\": \"or'
- Sadly, the additional
\
-escaping of the embedded "
chars. is a requirement either way, up to at least PowerShell 7.2.x, even though it shouldn't be necessary.
- It is due to a long-standing bug in how PowerShell passes arguments with embedded double-quotes to external programs; a - possibly opt-in - fix may be coming - see this answer.
- If you're using a 7.2.x version or a 7.3 preview version of PowerShell with the experimental feature named
PSNativeCommandArgumentPassing
enabled and the $PSNativeCommandArgumentPassing
preference variable set to either 'Standard'
or 'Windows'
, the \
-escaping is no longer needed, because PowerShell then (finally) does it for you; that is, findstr /n /l /c:'"name": "or'
would suffice.
PowerShell alternative: Select-String
:
As shown in Mathias R. Jessen's answer, you may alternatively use the Select-String
cmdlet, the more powerful PowerShell counterpart to findstr.exe
, not least to avoid quoting headaches (see above) and potential character-encoding issues.
Like findstr.exe
, Select-String
uses regular expressions by default; use -SimpleMatch
to opt for literal matching.
Unlike findstre.exe
, Select-String
is case-insensitive by default (as PowerShell generally is). Use -CaseSensitive
to make matching case-sensitive.
Select-String
wraps matching lines in objects that include metadata about each match; if you're interested in the line text only, use -Raw
in PowerShell (Core) 7+, or pipe to ForEach-Object Line
in Windows PowerShell.
While piping lines read from a file via Get-Content
works, it is much slower than the passing the file path as an argument directly to Select-String
, via its -LiteralPath
parameter (you may also pipe file-info objects obtained with Get-ChildItem
to it).
- This has the added advantage that the display representation of the matching lines includes the file name an line number (see below).
Thus, the equivalent of your (corrected) findstr.exe
call is:
Select-String -LiteralPath .\input.json -CaseSensitive -SimpleMatch -Pattern '"name": "or'
# Alternative:
Get-ChildItem .\input.json |
Select-String -CaseSensitive -SimpleMatch -Pattern '"name": "or'
You'll get the following output in the console (note the output-line prefix consisting of the file name and the line number):
input.json:3: {"name": "oren"}
Note that this is the for-display representation of the object of type [Microsoft.PowerShell.Commands.MatchInfo]
that Select-String
emitted for the matching line.