33

While working on my file servers, I have noticed one strange folder that broke my script. Folder has name consisting of only one character with ascii value 160 (non-breaking space, NBSP). Visually that name is the same as space character.

Briefly, I have Get-ChildItem being executed on this folder and it is entering endless loop. Command is in reality executed against parent folder and it returns again problematic folder, so my script got into endless loop.

You can easily simulate this on your own environment. In C:\temp folder create new folder whose name consists only of NBSP. You can type that with holding alt and pressing 0160 on numerical keyboard. After creating it, run

Get-ChildItem C:\Temp\ -Recurse

you will get endless list of folders without name, although I have only that one folder.

d-----        6/15/2017   2:20 PM
d-----        6/15/2017   2:20 PM
d-----        6/15/2017   2:20 PM
d-----        6/15/2017   2:20 PM
d-----        6/15/2017   2:20 PM
. . .

I tested this with PowerShell 4 and 5, on Server and Client OS and its the same behavior. Command Get-Item is having also issue with this name, and both switches -Path and -LiteralPath are behaving in the same way. I tried also [System.IO.Directory] class, but it was having the same issue.

Question: I have updated my script to report folders with this name as an error and skip it, but I am wondering is there some more smart way to do it? My goal would be to run Get-ChildItem or equivalent against such folder.

Is this a known issue? Would be be worth reporting it somewhere as a bug, if confirmed by more people?

Mark Wragg
  • 22,105
  • 7
  • 39
  • 68
Igor
  • 1,349
  • 12
  • 25
  • 6
    Yep, I see it too. Definitely a bug. `DirectoryInfo` works for me: `([IO.DirectoryInfo]'c:\temp').EnumerateFileSystemInfos('*', 'AllDirectories')` – wOxxOm Jun 15 '17 at 12:54
  • I can confirm this too and undoubtly this is somehow exploitable. I would encourage you to report it. – Lieven Keersmaekers Jun 15 '17 at 13:03
  • @wOxxOm can you still recurse into that NBSP folder should it contain another folder? Also, can you literally get dirinfo about the NBSP folder and not just "temp"? – Vesper Jun 15 '17 at 13:07
  • @Vesper, yes we can! As for the 2nd task, I had to add a slash: `[io.directoryinfo]'R:\1\ \'` – wOxxOm Jun 15 '17 at 13:11
  • For c:\temp works with or without final backslash, but for NBSP folder only with it. – Igor Jun 15 '17 at 13:13
  • 1
    And, yea, good old DIR /S works fine also (not in PoSh console, as there it is just alias to gci) – Igor Jun 15 '17 at 13:17
  • 1
    Looking at the recursion happening on the stack, I would assume this to be reproducable in any .Net language. – Lieven Keersmaekers Jun 15 '17 at 13:26
  • I have noticed the same behaviour today while answering [another question](https://stackoverflow.com/a/44570716/3439404). The bug appears for **any** folder name which contains `U+00A0` _No-Break Space_ not only for one-character folder name. Moreover, if such a folder contains a _commonly_ named folder, then `dir d:\test -Recurse | % {$_.FullName}` repeats a sequence of child items indefinitely… Finally, it throws `System.InsufficientExecutionStackException` or `CallDepthOverflow` error. – JosefZ Jun 15 '17 at 15:08
  • 5
    @LievenKeersmaekers was right. This is not a PowerShell issue, but a dotnet. I have opened an issue there. https://github.com/dotnet/corefx/issues/21096 – Igor Jun 16 '17 at 09:57
  • It seems this bug only occurs when the NBSP is the last character in the folder name. As pointed out by wOxxOm above adding the slash works around it. Sadly with PS we can only do that to the path input; the function calls .Net code rather that being itself recursive, so creating a proxy function to append that slash gives no joy. – JohnLBevan Jun 17 '17 at 22:36
  • 1
    I'd post your workaround as the answer, and file a bug report. This is surely not the expected behavior for the cmdlet. – PSGuy Jul 17 '17 at 01:09
  • Maybe [this](http://community.idera.com/powershell/powertips/b/tips/posts/finding-illegal-characters-in-paths-file-system-directory) can help? – Andrei Odegov Jul 19 '17 at 20:19
  • Issue is flagged as closed (as of a couple weeks ago). Not sure how long before it appears in a .NET update for us plebs. My current version of .NET appears to be 4.6.01590. Is this in the latest non-preview version (4.6.2, I think)? FWIW, my current version of PowerShell is at 5.0.10586.672 – Local Needs Aug 11 '17 at 18:11
  • I remember special device names like CON, AUX or PRN used for directories causing problems in Microsoft systems. – Zdenek Aug 15 '17 at 19:24
  • Are you able to use `-Filter '* *'` to target the objects with the offending character and fix them? – Maximilian Burszley Sep 19 '17 at 20:10

1 Answers1

3

As mentioned in the comment, you found an actual error that will hopefully soon being fixed.

However, there is a very acceptable workaround that you can apply with minimal effort while continuing to use Get-ChildItem without the need to exclude your folder.

The Unicode version of Get-ChildItem does not suffer from this problem. (Tested on Powershell 5.1 on a Windows 10 environment) To use it, simply replace

Get-ChildItem  -Path 'c:\__tmp' -recurse 

by

Get-ChildItem  -LiteralPath '\\?\c:\__tmp' -recurse 

Additional note

If you need to deal with UNC, the UNC unicode call is slightly different.

Get-ChildItem  -LiteralPath '\\?\UNC\127.0.0.1\c$\__tmp' -recurse 

Notice that I use for this to work properly the -LiteralPath parameter instead of -Path.

References

From Microsoft documentation

-LiteralPath

Specifies a path to one or more locations. Unlike the -Path parameter, the value of the -LiteralPath parameter is used exactly as it is typed. No characters are interpreted as wildcards. If the path includes escape characters, enclose it in single quotation marks. Single quotation marks tell Windows PowerShell not to interpret any characters as escape sequences.

source

Regarding the unicode prefix convention: Naming Files, Paths, and Namespaces

Bonus The unicode call also have the benefit of solving the 260 characters path length limit : see here

mklement0
  • 382,024
  • 64
  • 607
  • 775
Sage Pourpre
  • 9,932
  • 3
  • 27
  • 39