PowerShell: `ls` breaks down when path name contains hyphen enclosed in escaped brackets

Prerequisites

Steps to reproduce

I have a file .\o\abc [defg-0 hijk -lmn].pdf. Then I try all commands below to ls it. The first char y/x represents that the corresponding command works or not, i.e. prints the file or throw out error which is in ‘Error details’ part.

y ls '*`[defg*0 hijk -lmn`].pdf' -Recurse
y ls '*defg-0 hijk -lmn*.pdf' -Recurse
x ls '*`[defg-0 hijk -lmn`].pdf' -Recurse

Expected behavior

All three commands above work fine, i.e. print the file specified.

Actual behavior

Just as the first char y/x in each command line shows. It seems that hyphen is recognized as a special char although brackets are escaped.

Error details

Get-ChildItem: Cannot retrieve the dynamic parameters for the cmdlet. The specified wildcard character pattern is not valid: *\[defg-0 hijk -lmn\].pdf


### Environment data

```powershell
Name                           Value
----                           -----
PSVersion                      7.2.6
PSEdition                      Core
GitCommitId                    7.2.6
OS                             Microsoft Windows 10.0.19043
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0


### Visuals

_No response_

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 16 (8 by maintainers)

Most upvoted comments

This is all harder than it needs to be 😦

Amen to that.

If backward compatibility weren’t in the picture, I would eliminate the implicit recursion based on the leaf component of the -Path component altogether - it is simply too treacherous and confusing.

That is, the only way to search for a name or pattern in all directories of the subtree would then be to use either -Filter or -Include, and both -Path and -LiteralPath would consistently only specify the starting point for -Recurse.

Therefore, @iSazonov, backward compatibility also gets in the way of your suggestion, because you can (unfortunately) currently do something like Get-ChildItem $Home/*.txt -Recurse too look for *.txt files in the entire subtree, which would break if $Home/*.txt were to bind to -Include.

We have filter which passes the characters to the Windows API which treats * and ? but not [ ] as wildcards (not sure what happens on linux but it may treat them differently)

We have literalpath which should treat nothing as wildcards even though on windows * and ? are forbidden by the filesystem, on linux that would be how you request a file with those characters.

And path which treats all 3 as wildcards, unless they are backquoted (the backquote is a requirement of the wildcard class, not PowerShell syntax). However backquoted characters are not always processed correctly.

Since -literalpath does not work with -recurse , -filter will work for this case, but the -path won’t because of the backquote problem.

@iSazonov looking at the error, it seems that somewhere in processing the parameters something is not seeing `[ and `] as escaped and is trying to process what is inside the [ ... ] as a wildcard expression

@LqkUWp specifying -LiteralPath will prevent this happening.