In File Explorer on an NTFS volume, create the file: [abc].txt
Following this run:
ls '[abc].txt'
Directory: C:\Users\Dave
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2019-05-06 12:07 AM 0 [abc].txt
No output displayed.
Name Value
---- -----
PSVersion 6.2.0
PSEdition Core
GitCommitId 6.2.0
OS Microsoft Windows 10.0.17763
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0鈥
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
The file name can be displayed using tab completion, but the brackets are preceded by back ticks, which indicates that Windows can see the file and assumes that the brackets are special characters. When attempting to list the file using the ls command, the following error is generated:
ls : Cannot find path 'C:\Users\Dave\`[abc`].txt' because it does not exist.
At line:1 char:1
+ ls '.\`[abc`].txt'
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\Users\Dave\`[abc`].txt:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
Other commands generate no output or errors as well.
Get-FileHash '[abc].txt'
# Generates no output
1 | Out-File '[abc].txt'
# Generates error stating that the wildcard path did not resolve to a file
According to Microsoft's "About Quoting Rules" page, "When you enclose a string in single-quotation marks (a single-quoted string), the string is passed to the command exactly as you type it. No substitution is performed".
/cc @kwkam @mklement0
Short:
https://github.com/PowerShell/PowerShell/pull/9257 resolves this issue.
Long:
Most cmdlets that accept a path treats the first string parameter as -Path, which can do wildcard/glob. The command
ls '[abc].txt'
is the same as
Get-ChildItem -Path '[abc].txt'
where [abc].txt will be considered as a wildcard pattern which matches either a.txt/b.txt/c.txt, so we have to:
Get-ChildItem -Path '`[abc`].txt'
-LiteralPath to indicate that the path is literal:Get-ChildItem -LiteralPath '[abc].txt'
However, the first solution still does not work because the Get-ChildItem cmdlet is not handling the -Path argument correctly, when it contains escaped special character:
Get-ChildItem check if glob should be performed on -PathWhich means it will try to find a file literally named `[abc`].txt instead of [abc].txt
@kwkam Thanks for great comment! Should we add new test in #9257 related the issue?
And the related issues re file-creating cmdlets such as Out-File (and operator >) are #4726 and #9475. Related: #9225.
:tada:This issue was addressed in #9257, which has now been successfully released as v7.0.0-preview.2.:tada:
Handy links:
Most helpful comment
Short:
https://github.com/PowerShell/PowerShell/pull/9257 resolves this issue.
Long:
Most cmdlets that accept a path treats the first string parameter as
-Path, which can do wildcard/glob. The commandis the same as
where
[abc].txtwill be considered as a wildcard pattern which matches eithera.txt/b.txt/c.txt, so we have to:-LiteralPathto indicate that the path is literal:However, the first solution still does not work because the
Get-ChildItemcmdlet is not handling the-Pathargument correctly, when it contains escaped special character:Get-ChildItemcheck if glob should be performed on-PathWhich means it will try to find a file literally named
`[abc`].txtinstead of[abc].txt