Finding Files with Long File Names

Recently have been trying to organize a large Data Archiving project and during the evaluation of the process and discovery of the files to be archived we found that there was a lot of folders that couldn't be moved as a result of the path and\or file names exceeding the 260 character limit.  Having 9+ TB of data, you can imagine how many files there are an how time consuming it would be to find all those files.  Second to that if you were using the traditional file move within windows it would get stuck on the path being to long and generate an error:

As a result, the transfer would get stuck. Reminding us the fact that moving terabytes of data this could be cumbersome, not to mention the best way to mass archive folders.  Having said that if the end users are cleaning up their own data, it's a problem.

In order to prepare the data for move, it's best to try and get a list of these files ahead of time in order to decide how to handle the files.  Some may not be needed, some may require you to rename the files. 

In order to do that, I turned to powershell to provide us a list of where those files or folders are located.  However, a straight Get-ChildItem -Path "<PATH>" returns the following error:

Get-ChildItem : 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.

This is where Exporting the results to CSV helped.  But before I could do that I need a good powershell function to work with directories.  Lucky for me on TechNet there was the Get-FolderItem powershell script to assist.  Once I had that download I put it in my "Scripts" Folder.  You could put it wherever you want, however you need to reference it in your script, thus remember where you placed it.   Once I had that set, I created the following script:

### Find Long File Names ###

cd <PATH TO Get-FolderItem>
. ./Get-FolderItem.ps1
cd \

# Set path to root folder you want to find long file names and the output folder path

$path = "<path to search base>"
$outputfolderpath = "<Output Path for CSVs>"

$GetRootFolder = Get-ChildItem -path $path | ?{ $_.PSIsContainer }
foreach ($folder in $GetRootFolder)
$outputfile = ($outputfolderpath + $folder.Name + '_LongPaths.csv')
(Get-FolderItem -Path $folder.FullName | Where-Object {$_.FullPathLength -ge "248"})| Export-CSV "$outputfile"

You will see in the above script I set the search path, i.e. C:\LongFileDirectory.  This is the path that contains either the folders or files that you suspect that exceed the limit, or in my case the root path to where the archived folders\files were located.

The Output directory for me was a local temp file.  Essentially it's going to create a file for each sub folder that is below the root.  What you will notice is that any file that is created that has a 0KB file size means there were no "problems" in that sub-folder. 

In that file it will show a list of all the files or folders with long paths.

You will see the FullName column contains the full path, in this case I used the PSIsContainer in my script so it's returning only files and not just the folders.  However, you also see the ParentFolder Column which will show you the paths.

It's important to note here, there are options on what you can do from this point forward.  In our case after looking at the ParentFolder paths we could tell that a lot of this data was duplicated information or image files that we no longer needed to retain.  Most of them came from zip files that were download from our clients that were reference files years prior.  

Point being is at this juncture you could use the "FullName" column to target the files for renaming or deletion, or you could target the ParentFolder for mass deletion.  In our case that's exactly what we did.  We used Powershell in order to Import the CSV, and used the Get-Unique function to return just the list of problem folders.  In our case it took 100,000+ files down to less then 200 specific problem folders that we choose to delete.  That script is below if you wanted to use that as well.

$filelistpath = "<PATH TO CSV Filies Created Above>"
Get-ChildItem $filelistpath\*.* -Include *.csv
$folderlistfiles = Get-ChildItem $filelistpath\*.* -Include *.csv
foreach ($filepathlist in $folderlistfiles) 

$fullpath = $filelistpath + $filepathlist.Name

$longpath = Import-Csv $fullpath
$unique = $longpath | Get-Unique

foreach ($fubar in $unique)

$delpath = $fubar.ParentFolder
robocopy c:\Fullerton\Blank $delpath.Trimend('\') /mir