Tip: You can delete files and folders longer than 259 characters (long path).
I saw some people wasting a lot of time by map /unmap multiple drives to reduce length, delete the files manually, etc.
So I decided to explain that in an article in case you need to delete long path files.
I will show an easy way using the module AlphaFS to create, copy, remove and delete files / folders which support more than 32 000 characters.
Download (AlphaFS.2.0.1.zip) : https://github.com/alphaleonis/AlphaFS/releases/latest
The module is also available on PowerShell Gallery although the current version has only very few cmdlets available :
https://www.powershellgallery.com/packages/PSAlphaFS/1.0.0.0
I will publish another article to show how to do that without using the external module AlphaFS (although this module uses the same technique by importing kernel32.dll).
In this post, there are 2 parts :
Part 1 (Files) : Create, copy, move, search and delete
Part 2 (Folders) : Search and delete folders
===
DeleteFile function
https://msdn.microsoft.com/en-us/library/aa363915(VS.85).aspx
ANSI : The name is limited to MAX_PATH characters (260 characters).
UNICODE : To extend this limit to 32 767 wide characters, call the Unicode version of the function and prepend “\?\” to the path.”
===
Download (AlphaFS.2.0.1.zip) : https://github.com/alphaleonis/AlphaFS/releases/latest
Then, you have to unblock the file, otherwise, you will receive this eror : Import-Module : Could not load file or assembly ‘file:///C:\Demo\AlphaFS.2.0.1\lib\net451\AlphaFS.dll’ or one of its dependencies. Operation is not supported. (Exception from HRESULT: 0x80131515)
To unblock the file:
PowerShell : Unblock-File -Path 'C:\Demo\AlphaFS.2.0.1.zip'
or
GUI : right click, Properties and Unblock.
Let’s create a path of 362 characters for the test.
1 2 3 4 5 6 7 8 9 10 11 12 |
# .NET Framework 3.5 (ex: Windows 2008) Import-Module -Name 'C:\Demo\AlphaFS.2.0.1\lib\net35\AlphaFS.dll' # .NET Framework 4.5 (ex: Windows 2012) Import-Module -Name 'C:\Demo\AlphaFS.2.0.1\lib\net451\AlphaFS.dll' # Generate a long path (362 characters) $LongPath = "\\fs01\Test\$(((1..30) | %{"subfolder$_"}) -join '\')" $LongPath.Length # Create 30 subfolders (path = 362 characters) [Alphaleonis.Win32.Filesystem.Directory]::CreateDirectory($LongPath) |
I have now a very long path created for this demo:
1 |
$LongPath = '\\fs01\Test\subfolder1\subfolder2\subfolder3\subfolder4\subfolder5\subfolder6\subfolder7\subfolder8\subfolder9\subfolder10\subfolder11\subfolder12\subfolder13\subfolder14\subfolder15\subfolder16\subfolder17\subfolder18\subfolder19\subfolder20\subfolder21\subfolder22\subfolder23\subfolder24\subfolder25\subfolder26\subfolder27\subfolder28\subfolder29\subfolder30' |
===
PART 1: FILES
# Create
1 |
[Alphaleonis.Win32.Filesystem.File]::Create("$LongPath\file1.txt") |
It will create a file to : \\fs01\Test\subfolder1\…\subfolder30\file1.txt
===
# Move
1 |
[Alphaleonis.Win32.Filesystem.File]::Move("\\fs01\Test\file2.txt", "$LongPath\file2.txt") |
I created a demo file here : \\fs01\Test\file2.txt
I move this demo file from \\fs01\Test\file2.txt to \\fs01\Test\subfolder1\…\subfolder30\file2.txt
===
# Copy
1 |
[Alphaleonis.Win32.Filesystem.File]::Copy("\\fs01\Test\file3.txt", "$LongPath\file3.txt") |
I created a demo file here : \\fs01\Test\file3.txt
I copy this demo file from \\fs01\Test\file3.txt to \\fs01\Test\subfolder1\…\subfolder30\file3.txt
===
# Search
1 2 3 |
[Alphaleonis.Win32.Filesystem.Directory]::EnumerateFiles("\\fs01\Test\subfolder1", "*.txt", [System.IO.SearchOption]::AllDirectories) or [Alphaleonis.Win32.Filesystem.Directory]::GetFiles("\\fs01\Test\subfolder1", "*.txt", [System.IO.SearchOption]::AllDirectories) |
Note: The EnumerateFiles and GetFiles methods differ as follows: When you use EnumerateFiles, you can start enumerating the collection of names before the whole collection is returned; when you use GetFiles, you must wait for the whole array of names to be returned before you can access the array. Therefore, when you are working with many files and directories, EnumerateFiles can be more efficient.
It will return 3 files :
File1 : Created
File2: Moved
File3 : Copied
===
# Delete (one single file)
1 |
[Alphaleonis.Win32.Filesystem.File]::Delete("$LongPath\file1.txt") |
The file1.txt has been deleted.
===
# Delete (multiple files)
1 2 3 4 5 6 |
$files = [Alphaleonis.Win32.Filesystem.Directory]::EnumerateFiles("\\fs01\Test\subfolder1", "*.txt", [System.IO.SearchOption]::AllDirectories) foreach ($file in $files) { [Alphaleonis.Win32.Filesystem.File]::Delete($file) } |
The file2.txt and file3.txt have been deleted.
===
PART 2: FOLDERS
# Search (one folder and subfolders)
1 |
[Alphaleonis.Win32.Filesystem.Directory]::EnumerateDirectories("\\fs01\Test\subfolder1", "subfolder28", [System.IO.SearchOption]::AllDirectories) |
We search a subfolder “subfolder28”:
# Delete (one folder and subfolders)
1 2 3 4 5 |
$folderToDelete = [Alphaleonis.Win32.Filesystem.Directory]::EnumerateDirectories("\\fs01\Test", "*subfolder29", [System.IO.SearchOption]::AllDirectories) [Alphaleonis.Win32.Filesystem.Directory]::Delete($folderToDelete, $true) # Search and confirm that we have deleted subfolder29 and all subfolders. [Alphaleonis.Win32.Filesystem.Directory]::EnumerateDirectories("\\fs01\Test\subfolder1", "*", [System.IO.SearchOption]::AllDirectories) | Select -Last 1 |
We delete the folder \\fs01\Test\subfolder1\…\subfolder29\*.* and all subfolders.
To specify that the deletion is recursive I set $true for boolean parameter recursive.
1 |
[Alphaleonis.Win32.Filesystem.Directory]::Delete($folderToDelete, $true) |
To list overload definitions : [Alphaleonis.Win32.Filesystem.Directory]::Delete
To list static methods of File Class : [Alphaleonis.Win32.Filesystem.File] | Get-Member -Static -MemberType Method
Online documentation
File Class
http://alphafs.alphaleonis.com/doc/2.0/api/html/F5429666.htm
Directory Class
http://alphafs.alphaleonis.com/doc/2.0/api/html/26653682.htm