I am recursing a deep folder structure in order to retreive all folder paths like so:
$subFolders = Get-ChildItem $rootFolder -Recurse -Directory -ErrorVariable folderErrors | Select-Object -ExpandProperty FullName
NOTE: $rootFolder in my case is a network share. i.e. "\\server\DeptDir$\somefolder"
The $folderErrors
variable is correctly capturing all the FileTooLong exceptions so I want to create new PSDrives using the long Paths in order to recurse those long paths.
So I create a new PSDrive using this cmdlet:
new-psdrive -Name "long1" -PSProvider FileSystem -Root $folderErrors[0].CategoryInfo.TargetName
However, after creating a new PSDrive I am still getting PathTooLong Exceptions.
PS C:\>> cd long1:
PS long1:\>> dir
dir : The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.
At line:1 char:1
+ dir
+ ~~~
+ CategoryInfo : ReadError: (\\svr01\Dep...\Fibrebond ECO\:String) [Get-ChildItem], PathTooLongException
+ FullyQualifiedErrorId : DirIOError,Microsoft.PowerShell.Commands.GetChildItemCommand
I see no other way around this problem. Am I doing something incorrectly? Why is the new PSDrive throwing PathTooLong when I am creating a drive at the location where the path is too long?
Thanks
There is a local policy that is now available since Windows anniversary update.
Requirements are :
Windows Management Framework 5.1
.Net Framework 4.6.2 or more recent
Windows 10 / Windows server 2016 (Build 1607 or newer)
This policy can be enabled using the following snippet.
#GPEdit location: Configuration>Administrative Templates>System>FileSystem
Set-ItemProperty 'HKLM:\System\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -value 1
Otherwise, you can actually get to the paths longer than 260 characters by making your call to the unicode version of Windows API.
There's a catch though. This work only in Powershell 5.1 minimum.
From there, instead of making your call the standard way:
get-childitem -Path 'C:\Very long path' -Recurse
You will need to use the following prefix:
\\?\
Example
get-childitem -LiteralPath '\\?\C:\Very long path' -Recurse
For UNC path, this is slightly different, the prefix being \\?\UNC\
instead of \\
get-childitem -LiteralPath '\\?\UNC\127.0.0.1\c$\Very long path\' -Recurse
Important
When calling Get-ChildItem
unicode version, you should use the -LiteralPath
parameter instead of Path
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 them in single quotation marks. Single quotation marks tell Windows PowerShell not to interpret any characters as escape sequences.
source
Example
(get-childitem -LiteralPath '\\?\UNC\127.0.0.1\This is a folder$' -Recurse) |
ft @{'n'='Path length';'e'={$_.FullName.length}}, FullName
output
Here is the actual functional test I made to create the very long repository, query it to produce the output above and confirm I could create repository with more than 260 characters and view them.
Function CreateVeryLongPath([String]$Root,[Switch]$IsUNC,$FolderName = 'Dummy Folder',$iterations = 200) {
$Base = '\\?\'
if ($IsUNC) {$Base = '\\?\UNC\'}
$CurrentPath = $Base + $Root + $FolderName + '\'
For ($i=0;$i -le $iterations;$i++) {
New-Item -Path $CurrentPath -Force -ItemType Directory | Out-Null
$currentPath = $CurrentPath + $FolderName + '\'
}
}
Function QueryVeryLongPath([String]$Root,[Switch]$IsUNC) {
$Base = '\\?\'
if ($IsUNC) {$Base = '\\?\UNC\';$Root = $Root.substring(2,$Root.Length -2)}
$BasePath = $Base + $Root
Get-ChildItem -LiteralPath $BasePath -Recurse | ft @{'n'='Length';'e'={$_.FullName.Length}},FullName
}
CreateVeryLongPath -Root 'C:\__tmp\' -FolderName 'This is a folder'
QueryVeryLongPath -Root 'C:\__tmp\Dummy Folder11\'
#UNC - tested on a UNC share path
CreateVeryLongPath -Root '\\ServerName\ShareName\' -FolderName 'This is a folder' -IsUNC
QueryVeryLongPath -Root '\\ServerName\ShareName\' -IsUNC
Worth to mention
During my research, I saw people mentioning using RoboCopy then parse its output. I am not particularly fond of this approach so I won't elaborate on it. (edit: Years later, I discovered that Robocopy is part of Windows and not some third-party utility. I guess that would be an ok approach too, although I prefer a pure Powershell solution)
I also saw AlphaFS being mentionned a couple of time which is a library that allows to overcome the 260 characters limitation too. It is open sourced on Github and there's even a (I did not test it though) Get-AlphaFSChildItem
built on it available on Technet here
Other references
Long Paths in .Net
Naming Files, Paths, and Namespaces
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With