PowerShell Get-ChildItem -recurse error - it blocks at some of the 256 long directories name - see example to reproduce error

Dorin Ionescu 21 Reputation points
2022-02-20T06:48:38.627+00:00

The code lines and the error

cd C:\save\dell_inspiron_ubuntu\save\save_z570\more\dir123\soft\exo\sou_predare1\dir123GCP\ExoModulesExtensions\platform-stable-4.1.x\samples\wai-template\src\main\webapp\WEB-INF\conf\sample-portal\wcm\artifacts\nodetype-templates\siteBreadcrumbWebContent
  $ErrorActionPreference = 'Continue'
      $ErrorView = 'NormalView' #all error messages
      (Get-Date -UFormat '%Y-%m-%d %H:%M:%S').toString() + '.' + ((Get-Date).millisecond)
      Get-ChildItem -Force -recurse | Select-Object FullName, Name, BaseName, Extension, Length, Mode, Attributes,
          {$_.CreationTimeUTC.Ticks}, {$_.CreationTimeUTC.TimeOfDay},
          {$_.LastWriteTimeUTC.Ticks}, {$_.LastWriteTimeUTC.TimeOfDay},
          CreationTimeUTC, LastWriteTimeUTC, CreationTime, LastWriteTime, LastAccessTime > 2056_power_shell.txt
      (Get-Date -UFormat '%Y-%m-%d %H:%M:%S').toString() + '.' + ((Get-Date).millisecond)

2022-02-20 08:17:31.33
Get-ChildItem : The system cannot find the path specified.
At line:5 char:6

  • Get-ChildItem -Force -recurse | Select-Object FullName, Name, Ba …
  • ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  • CategoryInfo : NotSpecified: (:) [Get-ChildItem], Win32Exception
  • FullyQualifiedErrorId : System.ComponentModel.Win32Exception,Microsoft.PowerShell.Commands.GetChildItemCommand
    2022-02-20 08:17:31.58
  1. I run this command on 100 HDD with thousands of files and it appears only on some special cases, around the path length of 256. Most of the times works
    I reproduced the minimal directory file structure where if failed
    I can not attach it here (only images are allowed) so I shared the archive
    link to minimal archive that reproduces the error size 18k link here
    The archive does not contain any executables - only 2 "gtmpl" files of the Exo opensource samples
    It is the PATH that creates the error because of its exact length and configuration that breaks the MS code
    just unzip it into a Windows system root disc (directly on C: or D: or other one-letter names of an HDD)
    If you unzip on D: change the "cd c:..." command accordingly
    (I found the error in a subdirectory of the opensource Exo application - it has 100+ long path directories but the error appears only at some of them)
    Workaround
    I delete some specific directories so I can repeat the command - then try again and the error starts again later... I have to do that 10-20 times for an HDD because of this super tricky error
    I have to delete around 10 subdirectories on all my HDDs in order for this command to work - it is a very subtle logic error inside the MS code
    Probably there is a subtle logic error at an exact size around 256 because it works for longer directories (the command works in all these cases if you go up one directory or more but it arrives if you go down one or more directories on the path that I reproduced - if you create more directories and go up it works if you go down it crashes)
  2. I tried all the $ErrorActionPreference parameters (all the others are hiding the error - You do not see the code crash - you have a bad, shorter result without knowing that it all went wrong - so keep the $ErrorView and $ErrorActionPreference like I choose in order to have the feedback of the crash)
  3. You may need this to compare with your system
    $PSVersionTable

Name Value


PSVersion 7.2.1
PSEdition Core
GitCommitId 7.2.1
OS Microsoft Windows 10.0.19042
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0

(4) I added a letter "dell_inspiron_ubuntu --> dell_inspiron_ubuntu1" and it works OK
I deleted a letter I added a letter "dell_inspiron_ubuntu --> dell_inspiron_ubunt" and it works OK
The path length is 256 and who knows what code crash is inside the PowerShell while migrating from older versions (3.x) where it crashed at ALL long directories
By the way, you may have a default 3.x PowerShell version now - install the new one

Windows Server PowerShell
Windows Server PowerShell
Windows Server: A family of Microsoft server operating systems that support enterprise-level management, data storage, applications, and communications.PowerShell: A family of Microsoft task automation and configuration management frameworks consisting of a command-line shell and associated scripting language.
5,546 questions
0 comments No comments
{count} votes

Accepted answer
  1. MotoX80 34,346 Reputation points
    2022-02-20T23:55:14.9+00:00

    So try my script on a machine with PS 5.1.

    Is there some functionality in PS 7.2 that you need?

    1 person found this answer helpful.

5 additional answers

Sort by: Most helpful
  1. MotoX80 34,346 Reputation points
    2022-02-20T21:52:52.42+00:00

    it appears only on some special cases, around the path length of 256. Most of the times works

    Based on that statement, I wrote a script to test to see if PS had a problem with a specific file name length. I tested this on Win11 and PS5.1.

    I discovered that Powershell_ISE does not like long file names. I had to run the script in Powershell.exe.

    Since you have PS7.2 give this a try and see if it works. Note that I tweaked your folder name for my testing.

    cls
    $x = get-itemproperty HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem  -name LongPathsEnabled
    if ($x.LongPathsEnabled -eq 1) {
        "Long file names are enabled."
    } else { 
        "Long file names are NOT enabled."
    }
    Remove-Item -Path 'C:\temp\dell_inspiron_ubuntu' -Recurse 
    $start = 'C:\temp\dell_inspiron_ubuntu\save\save_z570\more\dir123\soft\exo\sou_predare1\dir123GCP\ExoModulesExtensions\platform-stable-4.1.x\samples\wai-template\src\main\webapp\WEB-INF\conf\sample-portal\wcm\artifacts\nodetype-templates\siteBreadcrumbWeb'
    "The starting length is {0}" -f $start.length  
    New-Item -Path $start -ItemType Directory | out-null
    1..25 | foreach {
        $Subfolder = "$start\$('x' * $_)"
        New-Item -Path $Subfolder -ItemType Directory | out-null
        $_ | out-file  $Subfolder\X.txt    # create a subfolder and put a file in there too.  
    }
    Get-ChildItem $start -recurse -File | foreach {
        "{0} - {1}" -f $_.fullname.length,  $_.fullname.Substring(($_.fullname.Length -50),50)
    }
    "Now read content."
    Get-ChildItem $start -recurse -File | foreach {
        Get-content $_.fullname
    }
    
    1 person found this answer helpful.

  2. Rich Matheisen 46,801 Reputation points
    2022-02-20T15:58:16.917+00:00

    The limitation isn't in PowerShell, it's in the operating system.

    Enable long file name support: enable-long-file-name-support-windows-10


  3. Rich Matheisen 46,801 Reputation points
    2022-02-20T20:57:42.863+00:00

    Instead of making that long directory name the working directory try doing it this way:

    Get-ChildItem  "\\?\C:\save\dell_inspiron_ubuntu\save\save_z570\more\dir123\soft\exo\sou_predare1\dir123GCP\ExoModulesExtensions\platform-stable-4.1.x\samples\wai-template\src\main\webapp\WEB-INF\conf\sample-portal\wcm\artifacts\nodetype-templates\siteBreadcrumbWebContent" -recurse
    

  4. Dorin Ionescu 21 Reputation points
    2022-02-20T23:28:57.753+00:00

    Unfortunately, MS code has a strange way to crush
    I executed your code that created a lot of files and then this (one with 265 works one crashed (in fact the crash could be at the next file - who knows who is the next file))

    PS C:\save>

    $ErrorActionPreference = 'Continue'
       $ErrorView = 'NormalView' #all error messages
       (Get-Date -UFormat '%Y-%m-%d %H:%M:%S').toString() + '.' + ((Get-Date).millisecond)
       Get-ChildItem -Force -recurse | foreach {
              "{0} - {1}" -f $_.fullname.length,  $_.fullname.Substring(
                  [math]::max($_.fullname.Length - 50, 0),
                  [math]::min($_.fullname.Length, 50))
         }
       (Get-Date -UFormat '%Y-%m-%d %H:%M:%S').toString() + '.' + ((Get-Date).millisecond)
    

    The result has more than 1600 characters so I have to attach it here


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.