4

Why would I need two sets of double quotes, to use find in powershell?

For example

here trying to use FIND as one would in cmd.exe, gives an error.

PS C:\Users\User> echo abc | find "a"
FIND: Parameter format not correct

PS C:\Users\User> find "a" a.a FIND: Parameter format not correct PS C:\Users\User>

One has to do

PS C:\Users\User> echo "abc" | find "`"a`""
abc
PS C:\Users\User>

(the backtick is an escape character in powershell)

So you need two sets of double quotes. An inner set that are escaped(Each of the two quotes in the inner pair, are escaped), and an outter set.

ECHO, or DIR don't need escaped quotes. (though granted they are internal to the shell), so an example more like FIND, might be XCOPY.

xcopy is an external command, as is find, though xcopy doesn't need that kind of thing. It's fine with one set of double quotes no escaping.

PS C:\Users\User> xcopy "a.a" "b.b"
Does b.b specify a file name
or directory name on the target
(F = file, D = directory)? f
C:a.a
1 File(s) copied
PS C:\Users\User>
barlop
  • 25,198

2 Answers2

1

Why would I need two sets of double quotes, to use find in Powershell?

xcopy doesn't need that kind of thing. It's fine with one set of double quotes no escaping.

That's because the quotes in xcopy are optional (unless the source or destination string contains spaces)

The quotes in find are compulsory:

"string" : Required. Specifies the group of characters that you want to search for. You must enclose string in quotation marks (that is, "string").

Source Find | Microsoft Docs

And:

PowerShell is stripping the outer quotes

Source windows - PowerShell stripping double quotes from command line arguments - Stack Overflow

This was all explained to you before in the duplicate to your previous question cmd.exe - Why can "find" not be used in PowerShell? - Super User


Further Reading

DavidPostill
  • 162,382
1

Why are you mixing a PowerShell alias with a DOS executable (find.exe)?

DOS/cmd.exe commands have requirements. It is why you are getting the issue you are seeing. Many cmd.exe/DOS commands do fin without quotes at all, some don't.

In PowerShell proper, you don't need double quotes for simple strings. You need them for variable expansion when a variable is included in a string and a few other formatting instances, but not what you are doing.

You are in Powershell, so, best to do this the PowerShell way. If this is throw-away code, or interactive console, stuff, using aliases is fine, but don't use aliases in functions, scripts, modules, aka production code.

As per Microsoft:

• Best Practices for aliases Best Practice for Using Aliases in PowerShell Scripts https://devblogs.microsoft.com/scripting/best-practice-for-using-aliases-in-powershell-scripts https://devblogs.microsoft.com/scripting/using-powershell-aliases-best-practices

Why worry about aliases in the first place?

What is the big deal about using aliases anyway? If they make the code easier to type, what is the harm in using them in scripts? There are two things at work when it comes to a script. The first is that no alias is guaranteed to exist—even aliases that are created by Windows PowerShell.

So, this ...

echo abc | find "a"

... should be this...

Get-Alias -Name echo | 
Format-Table -AutoSize
# Results
<#
CommandType Name                 Version Source
----------- ----                 ------- ------
Alias       echo -> Write-Output
#>

Write-Output -Object 'abc' | Select-Object 'a'

or this...

Write-Output -Object 'abc' | Select-String -Pattern 'a'

or this...

Select-String -Pattern 'a' -InputObject 'abc'

Results

<# abc #>

Get-Alias -Name echo | Format-Table -AutoSize

Results

<# CommandType Name Version Source


Alias echo -> Write-Output
#>

Get-Alias -Name xcopy | Format-Table -AutoSize

Results

<# Get-Alias : This command cannot find a matching alias because an alias with the name 'xcopy' does not exist. At line:1 char:1

  • Get-Alias -Name xcopy | Format-Table -AutoSize
  •   + CategoryInfo          : ObjectNotFound: (xcopy:String) [Get-Alias], ItemNotFoundException
      + FullyQualifiedErrorId : ItemNotFoundException,Microsoft.PowerShell.Commands.GetAliasCommand   
    

#>

As you can see the above is using cmd.exe/DOS executable, not an alias

So, change to this.

Get specifics for a module, cmdlet, or function

(Get-Command -Name Copy-Item).Parameters (Get-Command -Name Copy-Item).Parameters.Keys Get-help -Name Copy-Item -Examples Get-help -Name Copy-Item -Full Get-help -Name Copy-Item -Online

'.txt', '.xls' | ForEach-Object { Copy-Item -Path "d:\temp$PSItem" -Destination 'D:\Temp\ChildFolder' -WhatIf }

Results

<# What if: Performing the operation "Copy File" on target "Item: D:\temp\abc.txt Destination: D:\Temp\ChildFolder\abc.txt". What if: Performing the operation "Copy File" on target "Item: D:\temp\account.txt Destination: D:\Temp\ChildFolder\account.txt". ... #>

about_Command_Precedence

If you do not specify a path, PowerShell uses the following precedence order when it runs commands for all items loaded in the current session:

1 - Alias

2 - Function

3 - Cmdlet

4 - External executable files

(programs and non-PowerShell scripts)

Therefore, if you type "help", PowerShell first looks for an alias named help, then a function named Help, and finally, a cmdlet named Help. It runs the first help item that it finds.

For example, if your session contains a cmdlet and a function, both named Get-Map, when you type Get-Map, PowerShell runs the function.

Yes, you can use cmd.exe/DOS executable in a PowerShell command or script, but when you do, they must conform to cmd.exe/DOS particulars. Calling external executables from Powershell is a well-documented thing.

• PowerShell: Running Executables https://social.technet.microsoft.com/wiki/contents/articles/7703.powershell-running-executables.aspx

Try to avoid mixing cmd.exe/DOS executables in PowerShell scripts and use the PowerShell equivalents instead. Note: There are times this cannot be avoided, but not in your use case as posted.

Update As per your comment

write-host abc | select-string -pattern "a" shows the result expected

  • abc. But This unfortunately also shows abc. write-host abc | select-string -pattern "z"

That should have been Write-Output, not Write-Host, Corrected the above.

No need for the Write-Host or Write-Output thing at all for what you are doing. Output to the screen is the PoweShelll default unless you tell it otherwise. If you are saying, you only want the letter 'a' of the string, then you need to pass it as an array, not a single string

'a','b','c' | 
Select-String -Pattern 'a'
# Results
<#
a
#>

'a','b','c' | Select-String -Pattern 'z'

Results

<#

#>

Here is another way to split a single string into an array.

('abc').ToCharArray() | 
Select-String -Pattern 'a'

You could also use the .Net namespace directly

[regex]::Match('abc','a').Value
# Results
<#
a
#>

Results

<#

#>

PowerShell is an Object-Oriented language and expects and emits objects by default, not strings.

You can convert things to strings or pass in strings in several different ways for comparison, matching, reporting needs.

postanote
  • 5,136