删除目录,无论是否超过260个字符的限制

55

我正在编写一个简单的脚本,在特定天数后删除USMT迁移文件夹:

## Server List ##
$servers = "Delorean","Adelaide","Brisbane","Melbourne","Newcastle","Perth"

## Number of days (-3 is over three days ago) ##
$days = -3

$timelimit = (Get-Date).AddDays($days)

foreach ($server in $servers)
{
    $deletedusers = @()
    $folders = Get-ChildItem \\$server\USMT$ | where {$_.psiscontainer}
    write-host "Checking server : " $server
    foreach ($folder in $folders) 
    {
        If ($folder.LastWriteTime -lt $timelimit -And $folder -ne $null)
        {
            $deletedusers += $folder
            Remove-Item -recurse -force $folder.fullname
        }
    }
        write-host "Users deleted : " $deletedusers
        write-host
}

然而,我一直在遇到可怕的错误提示:Remove-Item : 指定的路径、文件名或两者都太长。完全限定的文件名必须少于 260 个字符,目录名必须少于 248 个字符。

我一直在寻找解决方法和替代方案,但它们都围绕着我关心文件夹中有什么。

我希望有一个更简单的解决方案,因为如果文件夹被标记为删除,我并不真正关心其中内容。

除了 Remove-Item -recurse 之外,是否有其他本地PowerShell cmdlet可以实现我想要的功能?

17个回答

60

我经常在Node项目中遇到这个问题。它们嵌套依赖项,一旦git克隆,就很难删除它们。我发现的一个不错的Node实用程序是rimraf

npm install rimraf -g
rimraf <dir>

2
太好了!Robocopy解决方案部分起作用,它删除了一些文件但不是全部。这个Rimraf完美无缺。非常感谢@Andy! - Allan.C

48

正如CADII在另一个答案中所说:Robocopy 能够创建超过260个字符的路径。Robocopy 还能够删除这样的路径。如果您想要删除包含超长名称的路径,您可以将某个空文件夹镜像到该路径上。

例如:

robocopy C:\temp\some_empty_dir E:\temp\dir_containing_very_deep_structures /MIR

以下是Robocopy参考文献,了解其参数和各种选项。


我可以确认这个解决方案是可行的,而且当我遇到同样的问题时,我也使用了它。 - mguassa
非常感谢您!我已经试图寻找一个工具来删除损坏的文件夹名称多年了。 - dotdawtdaught
这应该是答案... 它简洁高效,没有使用第三方工具。 - Egli Becerra
这对我有用,但是在robocopy镜像后,我不得不添加一个删除步骤(Remove-Item)。我剩下了E:\ temp \ dirname和空目录内容。非常感谢。我已经试图弄清楚这个问题一段时间了! - Michele

29

我已经创建了一个 PowerShell 函数,可以使用提到的 robocopy 技术 删除长路径(>260):

function Remove-PathToLongDirectory 
{
    Param(
        [string]$directory
    )

    # create a temporary (empty) directory
    $parent = [System.IO.Path]::GetTempPath()
    [string] $name = [System.Guid]::NewGuid()
    $tempDirectory = New-Item -ItemType Directory -Path (Join-Path $parent $name)

    robocopy /MIR $tempDirectory.FullName $directory | out-null
    Remove-Item $directory -Force | out-null
    Remove-Item $tempDirectory -Force | out-null
}

使用示例:

Remove-PathToLongDirectory c:\yourlongPath

2
提醒:在Windows 10版本14393(周年更新)中,.NET的路径限制错误已经被修复。您需要在本地策略中启用长路径支持,这样您就可以随心所欲地处理长路径,而不必求助于P / Invoke或robocopy。 - bluuf
2
这个像梦一样好用。而我却用了几个月的时间来使用subst z: myLongPath。 - Dean Meehan
1
这是本页面上唯一对我有效的解决方案。谢谢! - AndyJ
如果目录在Windows Server 2016中怎么办? - Senior Systems Engineer

22

这个答案在过去的一些时候对我起作用了,但是无法删除我的 node_modules 文件夹。对于这种情况,我采用了另一个答案,因为那个时候我已经安装了 Node。 - Jeroen
我也试过了,但它可能会在带有空格的目录中删除错误的内容(尽管这是可以修复的)。 - arberg

21

我前段时间学到了一个技巧,通常可以解决长文件路径的问题。显然,在使用一些Windows API时,某些函数将流经无法处理长文件名的旧代码。然而,如果按特定方式格式化路径,则可以避免旧代码。解决此问题的技巧是使用“\\?\”前缀引用路径。需要注意的是,并非所有API都支持此功能,但在我这个特定案例中,它对我起了作用,请参见我的以下示例:

以下示例失败:

PS D:\> get-childitem -path "D:\System Volume Information\dfsr" -hidden


Directory: D:\System Volume Information\dfsr


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a-hs        10/09/2014  11:10 PM     834424 FileIDTable_2
-a-hs        10/09/2014   8:43 PM    3211264 SimilarityTable_2

PS D:\> Remove-Item -Path "D:\System Volume Information\dfsr" -recurse -force
Remove-Item : 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
+ Remove-Item -Path "D:\System Volume Information\dfsr" -recurse -force
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : WriteError: (D:\System Volume Information\dfsr:String) [Remove-Item], PathTooLongExcepti
on
+ FullyQualifiedErrorId : RemoveItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand

PS D:\>

然而,在路径前加上 "\\?\" 可以使命令成功执行:

PS D:\> Remove-Item -Path "\\?\D:\System Volume Information\dfsr" -recurse -force
PS D:\> get-childitem -path "D:\System Volume Information\dfsr" -hidden
PS D:\>

那是一个很棒的技巧。我得尝试一下。通常当我遇到限制时,并没有做太过奇特的事情,只是解析文件夹结构或删除文件等。谢谢! - mhouston100
5
没有错误,但它也没有删除文件夹。 - rainabba
3
这个命令适用于我的电脑,运行在Windows 10和PowerShell 5.1环境下。命令如下:Remove-Item -Recurse -Force -Path "\?$($_.FullName)"。 - arberg
在PS 5.1上删除具有长路径的文件夹,但在PS 7.1上无法删除(没有错误)(在Windows Server 2019上)。 - Andy Arismendi
PS 7.1(核心)能够在 Windows Server 2019 上删除没有前缀的文件夹。 - Andy Arismendi

10

如果您已安装了ruby,您可以使用Fileman:

gem install fileman

安装后,您只需要在命令提示符中运行以下命令:

fm rm your_folder_path

如果你在Windows上开发node.js应用,这个问题会让你非常头疼,因此fileman在有时候删除所有垃圾文件时变得非常方便。


这是一个特定情况下的好答案,但当时它们是生产服务器,不幸的是没有 Ruby! - mhouston100
真是荒谬,我得安装Ruby,然后安装开发工具包,再安装一个Gem来删除一个文件夹,但这确实完成了工作。 - rainabba
这太棒了,它在一瞬间删除了一个巨大的树。谢谢你,谢谢你,谢谢你。 - Bill Rawlinson

9

我本来希望不必这么做,但是我阅读的越多,越发现没有其他选择了。感谢提供链接。 - mhouston100
7
“dir”似乎也出现了问题。 - StuperUser
最佳答案在这里:https://dev59.com/F2Qo5IYBdhLWcg3wBLco#33692148 - luiscla27

7

如果你只是在删除文件,我会使用一个函数来缩短文件名,然后再进行删除。

    function ConvertTo-ShortNames{
    param ([string]$folder)
    $name = 1
    $items = Get-ChildItem -path $folder
    foreach ($item in $items){
        Rename-Item -Path $item.FullName -NewName "$name"
        if ($item.PSIsContainer){
            $parts = $item.FullName.Split("\")
            $folderPath = $parts[0]
            for ($i = 1; $i -lt $parts.Count - 1; $i++){
                $folderPath = $folderPath + "\" + $parts[$i]
            }
            $folderPath = $folderPath + "\$name"
            ConvertTo-ShortNames $folderPath
        }
        $name++
    }
}

我知道这是一个老问题,但我认为我会在这里放置它,以防有人需要它。


这对于 Windows 机器上的 node_modules 文件夹非常有效。 - Jaans
救世主。谢谢! - jcolebrand
如果有人需要的话,只需把它放进去即可。顺便说一句,这是一个非常好的解决方案。( : - p._phidot_

3

有一种解决方法是使用基础类库项目中的Experimental.IO。您可以在poshcode上找到它,或从作者的博客下载。260限制来自于.NET,因此要么使用这种方法,要么使用不依赖于.NET的工具(如@Bill建议的cmd / c dir)。


2

如果要让我的Robocopy在1、2和3中工作

  1. 首先创建一个空文件夹,比如c:\emptydir
  2. ROBOCOPY c:\emptydir c:\directorytodelete /purge
  3. rmdir c:\directorytodelete
请注意,以上内容仅供参考。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接