Powershell get-childitem works different with long-path prefix (\\?\)

371 Views Asked by At

I have different results in these two cases:

  • case 1: Get-ChildItem -Path "\\?\UNC\very\long\path"
  • case 2: Get-ChildItem -Path "\\very\long\path"

If the long path is less than 260 characters long, I have diferent results.

  • case 1: Zero child items returned.
  • case 2: all the child items expected.

For getting same results, I should do different in case 1:

Get-ChildItem -Path "\\?\UNC\very\long\path\*"

Why this difference? I use \\?\UNC prefix because the fullpath is variable and I do not know it.

Perhaps I should use \* wildcard in both cases?

1

There are 1 best solutions below

1
mklement0 On BEST ANSWER

You're seeing a bug in Windows PowerShell that surfaces when you pass literal paths (non-wildcard) paths using a long-path prefix (\\?\ for local paths, \\?\Unc\ for UNC paths) to the (possibly positionally implied) -Path parameter. See the bottom section for details.

To work around it, use the -LiteralPath parameter instead, which is the right thing to do for non-wildcard paths anyway:

Get-ChildItem -LiteralPath \\?\UNC\server1\share1\very\long\path

Note:

  • PowerShell (Core) 7+ is no longer affected, because it has implicit support for long paths; that is, you don't need the long-path prefixes anymore.

  • However, these prefixes should still be accepted, which is something that is partially broken up to at least PowerShell 7.3.5 - see GitHub issue #10805


Windows PowerShell bug details:

The bug surfaces when you pass a non-wildcard root path that has a long-path prefix to -Path, which applies to both using the local and the UNC forms of the prefix, though the symptoms differ:

# UNC root path: 
# NO OUTPUT
Get-ChildItem -Path \\?\UNC\server1\share1

# LOCAL root path:
# -> SPURIOUS ERROR "Cannot retrieve Cannot retrieve the dynamic parameters for the cmdlet. ..."
Get-ChildItem -Path \\?\C:\

Appending at least one additional path component makes the problem go away; e.g.:

# Both OK, due to addition of another path component.
Get-ChildItem -Path \\?\UNC\server1\share1\subfolder
Get-ChildItem -Path \\?\C:\Windows

Curiously, however, the local form doesn't support wildcards on the level of the drive root:

# !! NO OUTPUT
Get-ChildItem -Path \\?\C:\*

# By contrast, wildcards DO work with the UNC prefix at the 
# top-level of the share
Get-ChildItem -Path \\?\UNC\server1\share1\*

As an aside:

  • Irrespective of whether a long-path prefix is used or not, wildcard matching of UNC share names is unsupported and quietly returns nothing.

  • That is, you cannot use * in order to discover available shares on a given server; something like Get-ChildItem -Path \\server1\* or Get-ChildItem -Path \\?UNC\server1\* never produces output.