在Windows中如何查找路径长度大于260个字符的文件?

100

我在 XP Windows 脚本中使用 xcopy 命令来递归地复制一个目录,但是一直收到“内存不足”错误提示。我了解这是因为我正在尝试复制的某个文件路径太长了。我可以很容易地缩短路径长度,但不幸的是,我无法确定哪些文件违反了路径长度限制。被复制的文件会输出到标准输出(我将其重定向到日志文件),但错误消息会打印到终端上,因此我甚至无法大致确定给出错误信息的目录。


在Windows 7上,我如何查找文件名太长的所有文件? - phuclv
9个回答

129

执行 dir /s /b > out.txt 命令,然后在 260 位置添加一个指南。

在 PowerShell 中使用 cmd /c dir /s /b |? {$_.length -gt 260} 命令。


1
dir /s /b > out.txt 做得很好。谢谢。“'Get-ChildItem' 不是内部或外部命令,也不是可运行的程序或批处理文件。”我猜我没有 PowerShell。 - WestHamster
1
@WestHamster,您需要在PowerShell控制台中运行该命令。 - Rami A.
6
出现错误信息:Get-ChildItem : 指定的路径、文件名或两者都太长。完全限定的文件名必须少于 260 个字符,目录名必须少于 248 个字符。 同时只有缩短后的路径被打印出来,例如 D:\Dropbox\ProY...sh._setbinddata。这些正是我想要查找的路径,但我无法看到整个路径!有什么解决办法吗? - MiniGod
1
我是唯一一个无法让它正常工作的人吗?使用Win7 64位家庭普通版,Powershell 2.0-当我创建一个具有很长名称(240个字符)的测试文件,然后将其所在的目录重命名为同样具有很长名称时,“Get-ChildItems -r *”不再看到该文件...只有“dir / s / b”对我有用。 - Jonas Heidelberg
看看我的答案,以了解如何在 PowerShell 中实现此目标,这样你就可以找到有问题的文件名(超过 260 个字符的文件名),或者选择忽略它们。 - Jonno
显示剩余4条评论

40

我为此创建了路径长度检查器工具,这是一个漂亮的免费GUI应用程序,您可以使用它来查看给定目录中所有文件和目录的路径长度。

我还编写并发布了一个简单的PowerShell脚本以获取文件和目录长度。它将输出文件的长度和路径,并可选择将其写入控制台。它不限于仅显示超过某个长度的文件(容易修改),但会按长度降序显示它们,因此仍然非常容易看出哪些路径超过您的阈值。以下是脚本:

$pathToScan = "C:\Some Folder"  # The path to scan and the the lengths for (sub-directories will be scanned as well).
$outputFilePath = "C:\temp\PathLengths.txt" # This must be a file in a directory that exists and does not require admin rights to write to.

$writeToConsoleAsWell = $true   # Writing to the console will be much slower.
 
# Open a new file stream (nice and fast) and write all the paths and their lengths to it.
$outputFileDirectory = Split-Path $outputFilePath -Parent
if (!(Test-Path $outputFileDirectory)) { New-Item $outputFileDirectory -ItemType Directory }
$stream = New-Object System.IO.StreamWriter($outputFilePath, $false)
Get-ChildItem -Path $pathToScan -Recurse -Force | Select-Object -Property FullName, @{Name="FullNameLength";Expression={($_.FullName.Length)}} | Sort-Object -Property FullNameLength -Descending | ForEach-Object {
    $filePath = $_.FullName
    $length = $_.FullNameLength
    $string = "$length : $filePath"
     
    # Write to the Console.
    if ($writeToConsoleAsWell) { Write-Host $string }
  
    #Write to the file.
    $stream.WriteLine($string)
}
$stream.Close()

2
有趣的脚本,但我仍然遇到了这个错误:Get-ChildItem:指定的路径、文件名或两者都太长。完全限定的文件名必须少于260个字符,目录名必须少于248个字符。 - zkurtz
非常优秀的工具!!我有大量数据,想在WD MyCloud硬盘驱动器上创建备份。通过这个工具,我了解到在硬盘驱动器上创建文件夹结构的最大长度。谢谢。 - NJMR
很棒的工具!我用它创建了一个脚本,能够查找所有路径长度超过247个字符的文件/文件夹,这是Synology Drive客户端在Windows中的限制。主要代码是PathLengthChecker.exe RootDirectory="C:\[MyFolder]" MinLength=248,而需要使用echo SELECT sync_folder FROM session_table;| sqlite3.exe %LocalAppData%\SynologyDrive\data\db\sys.sqlite来以编程方式获取共享文件夹。(如果您对完整代码有兴趣,请随时询问。) - Kar.ma
很棒的工具,谢谢。为了我的两个Synology NAS之间的Rsync-Job,我需要知道所有文件名长度超过143个字符的文件。这不是整个路径长度,而只是每个文件名的最大长度。我该如何找到这样的文件名? - PeterCo
1
嗨 @PeterCo,你仍然可以使用上面的PowerShell脚本,但是不要使用$_.FullName,而应该在所有地方替换为$_.Name;这将给你文件名而不是完整路径。 - deadlydog

31

如果你不能或不想安装PowerShell,可以采用简单解决方案的改进版本,只需运行:

dir /s /b | sort /r /+261 > out.txt

或者(更快):
dir /s /b | sort /r /+261 /o out.txt

注意,长度超过260个字符的行将排在列表的顶部。请注意,在SORT列参数中必须添加1(/+n)。


感谢您的改进。我的情况是我无法在Windows 2003上安装Powershell。已投赞成。 - preOtep
你能详细解释一下为什么必须加1吗? - Xonatron
有没有一种方法可以按行长度对输出文件进行排序? - Xonatron
@Xonatron,"而且行长超过260" - cliffclof
点赞。我认为这也应该提到SUBST,以缩短路径为驱动器ftw。 - cliffclof

10
我做了一份备选答案,使用PowerShell,但是我的代码可以将列表保存到文件中。如果有人需要类似的内容,我会在这里分享。
警告:代码会覆盖当前工作目录下的“longfilepath.txt”。虽然这种情况不太可能发生,但以防万一!
特意将其放在一行中:
Out-File longfilepath.txt ; cmd /c "dir /b /s /a" | ForEach-Object { if ($_.length -gt 250) {$_ | Out-File -append longfilepath.txt}}

详细说明:

  1. 运行PowerShell
  2. 浏览到您要检查文件路径长度的目录(C:可行)
  3. 复制并粘贴代码[右键单击以在PowerShell中粘贴,或按Alt + Space> E> P]
  4. 等待直到完成,然后查看文件:cat longfilepath.txt | sort

说明:

Out-File longfilepath.txt ; – 创建(或覆盖)名为 'longfilepath.txt' 的空文件。分号用于分隔命令。

cmd /c "dir /b /s /a" | – 在PowerShell上运行dir命令,/a 显示所有文件,包括隐藏文件。| 用于管道。

ForEach-Object { if ($_.length -gt 250) {$_ | Out-File -append longfilepath.txt}} – 对于每一行(表示为 $_),如果长度大于250,则将该行追加到文件中。


3

来源于http://www.powershellmagazine.com/2012/07/24/jaap-brassers-favorite-powershell-tips-and-tricks/

Get-ChildItem –Force –Recurse –ErrorAction SilentlyContinue –ErrorVariable AccessDenied

第一部分只是遍历这个文件夹和子文件夹;使用-ErrorVariable AccessDenied意味着将有问题的项目推入PowerShell变量AccessDenied

然后你可以像这样扫描变量:

$AccessDenied |
Where-Object { $_.Exception -match "must be less than 260 characters" } |
ForEach-Object { $_.TargetObject }

如果您不关心这些文件(在某些情况下可能适用),只需删除-ErrorVariable AccessDenied部分即可。

问题在于$_.TargetObject中不包含违反MAX_PATH的文件的完整路径,只有目录名称和有问题文件的父目录名称。我正在寻找一个非Robocopy或Subst或Xcopy的解决方案,并将在找到可行解决方案后发布。 - user66001

2

1
Chrome标记此下载文件包含病毒。 - Shaun

1

令人惊讶的是,这个问题仍然很重要。虽然E235给了我基础,但没有一个答案完全符合我的要求。我还打印出名称的长度,以便更容易地看到需要修剪多少个字符。

Get-ChildItem -Recurse | Where-Object {$_.FullName.Length -gt 260} | %{"{0} : {1}" -f $_.fullname.Length,$_.fullname }

1

你可以重定向stderr。

更多解释请参考这里。一个示例命令如下:

MyCommand >log.txt 2>errors.txt

应该获取您正在查找的数据。

此外,作为一个技巧,如果路径以\\?\为前缀(msdn),Windows将绕过该限制。

如果您有一个以长路径开头的根或目标,则可能会使用SUBST

SUBST Q: "C:\Documents and Settings\MyLoginName\My Documents\MyStuffToBeCopied"
Xcopy Q:\ "d:\Where it needs to go" /s /e
SUBST Q: /D

重定向标准输出和错误信息应该足以让我知道大文件在哪里,谢谢。 命令 > 文件 2>&1 - WestHamster
那会起作用,但我的命令“应该”将错误分离到一个单独的文件中。 - SeanC
\?\ 看起来也不错。但我无法让以下命令正常工作: xcopy /s \?\Q:\nuthatch \?\Q:\finch - WestHamster
嗯...似乎\\?\在命令行中不起作用。添加了另一个使用SUBST的想法。 - SeanC
不幸的是,subst 不会太有用,因为该命令属于以下类型: xcopy /s q:\nuthatch q:\finch<br/> 而长路径嵌入在 nuthatch 的某个未知位置下。 - WestHamster

0

对于路径大于260个字符的情况:
您可以使用:

Get-ChildItem | Where-Object {$_.FullName.Length -gt 260}

14 个字符的示例:
查看路径长度的方法:

Get-ChildItem | Select-Object -Property FullName, @{Name="FullNameLength";Expression={($_.FullName.Length)}

获取大于14的路径:
Get-ChildItem | Where-Object {$_.FullName.Length -gt 14}  

截图:
输入图像描述

对于文件名大于10个字符的情况:

Get-ChildItem | Where-Object {$_.PSChildName.Length -gt 10}

截图:
输入图像描述


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