Powershell 可以用来重命名路径长度超过 260 个字符的文件吗?

Powershell 可以用来重命名路径长度超过 260 个字符的文件吗?

我有数百个文件,其路径长度超过 260 个字符,我想重命名它们。使用 Powershell,我可以使用 找到长名称cmd /c dir /s /b |? {$_.length -gt 260},但实际的 cmdlet 不支持长文件名:Get-Item 将返回

“无法找到路径 [长路径],因为它不存在”

我读到一个名为 NTFSSecurity 的模块可以处理长路径,但到目前为止我只知道它可以使用名为 Get-ChildItem2 的 cmdlet 列出文件。我仍然不知道如何通过这种方式重命名文件。

在 Powershell 之外,我发现了一个名为 TLPD 的工具可以列出文件,但仅此而已。

到目前为止,我只能通过手动重命名父文件夹来解决这个问题,这样路径就变得足够短以便于访问(我可以使用 Powershell 模拟这个过程——但我希望有一种更简单的方法)

编辑:澄清一下,我想保留这些文件而不是尽可能地删除它们。

答案1

我写了一个可以运行的脚本。感谢 jftuga 的替代建议。

# This script searches through the search_path, finds file paths that are longer than total_path_length_threshold, and truncates the filename

### user settings ###

$test_run = $true                   # set to $false to start renaming for real
$search_path = "C:\my_folder\"      # the path to search for long names
$total_path_length_threshold = 260  # the length threshold to test
$characters_to_truncate = 5         # the number of characters to strip from the end of long filenames (a new identifier will also be added)
$log_file_path = "c:\my_folder\long_filename_log.txt"  # log file location

$virtual_drive = "v:"               # used for temporary processing using subst. Must look like "v:" and not like "v:\"

### end of user settings ###

Out-File $log_file_path
"Test run = $test_run" | Tee-Object $log_file_path -Append
"search_path = $search_path " | Tee-Object $log_file_path -Append
"total_path_length_threshold = $total_path_length_threshold " | Tee-Object $log_file_path -Append
"characters_to_truncate = $characters_to_truncate " | Tee-Object $log_file_path -Append

$counter = 0  # counter for creating new unique filenames
$collection = cmd /c dir $search_path /s /b |? {$_.length -gt $total_path_length_threshold }
$count_paths = ($collection | measure).count - 1

foreach ($path in $collection) {
    echo "found long path: $path"

    # get the parent's path
    $parent_path = Split-path -path $path

    # mount the parent to a virtual drive
    subst $virtual_drive $parent_path

    # get leaf element
    $leaf = split-path -leaf $path

    # make new short path
    $short_virtual_path = join-path $virtual_drive $leaf

    # get the long-name item 
    $item = Get-Item -LiteralPath $short_virtual_path

    if ($item -is [System.IO.fileinfo]) {
        # log long filename path
        "item $counter : Long filename path: $path" | Out-File $log_file_path -Append

        $filename = $item.name  #get the full filename

        # get filename extension
        $filename_extension = $item.Extension

        # get filename without extension:
        $basename = $item.BaseName    
        $basename_length = $basename.length 

        # give the new filename a unique index, to avoid duplicate filenames
        $new_index = "X" + $counter + "X"
        # the actual number of characters to cut is characters_to_truncate + new_index length
        $adjusted_characters_to_truncate = $characters_to_truncate + $new_index.length 

        if ( $basename_length -gt $adjusted_characters_to_truncate ) {
            $length_to_use = $basename_length - $adjusted_characters_to_truncate

            # shorten the filename by truncating it by specified num of char
            $new_filename = $basename.substring(0, $length_to_use ) + $new_index + $filename_extension

            # log the new filename path
            $new_path = $parent_path + $new_filename
            "item $counter : new filename path: $new_path " | Out-File $log_file_path -Append

            if (!$test_run) {
                # rename the file

                Rename-Item -LiteralPath $short_virtual_path $new_filename
            }

        }

    }

    $counter = $counter + 1

    #unmount the virtual drive
    subst v: /d
}

"Found $count_paths paths." | echo 

答案2

这就是如何删除具有非常长的路径名的文件夹和文件的方法,尽管不是在 powershell 中。

mkdir c:\alfa\bravo\charlie\delta\echo\foxtrot\golf\hotel\india\julliett\kilo\lima\mike\november\oscar\papa\quebec\romeo\sierra\tango\uniform\victor\whiskey\xray\yankee\zulu

join j: c:\alfa\bravo\charlie\delta\echo\foxtrot\golf\hotel\india\julliett
j:
subst k: j:\kilo\lima\mike\november\oscar\papa\quebec\romeo\sierra
k:
subst l: k:\tango\uniform\victor\whiskey
l:
rd /s/q xray
k:
rd /s/q tango
j:
rd /s/q kilo
c:
rd /s/q alfa

subst l: /d
subst k: /d
subst j: /d

总体概念是链接多个subst命令,以便它们嵌套在文件夹结构深处。您可能需要深入大约 6 个驱动器号。然后,您可以从最深层开始删除文件夹,然后遍历路径返回并退出。完成后,您可以删除使用该命令创建的驱动器号subst

答案3

有一个很酷的节点实用程序可以完成这个工作,叫做里姆拉夫如果你已经安装了节点,只需通过 npm 安装它

npm install -g rimraf
用法:rimraf dir

你也可以使用 robocopof,它能够创建长度超过 260 个字符限制的路径,并且能够删除它们

Robocopy 页面

从安装微软页面

答案4

要使用 robocopy 删除路径,您可以使用/purge空目录的参数。

CMD示例:
Robocopy.exe C:\temp\SourceDir C:\Temp\EmptyDir /Purge

这是SourceDir要删除的目录

这可以很容易地与 PowerShell 配对

PowerShell 示例:

$Paths = Get-Content C:\Temp\DeleteDirectories
ForEach($Path in $Paths){
   Robocopy.exe $Path C:\Temp\EmptyDir /Purge
           }

这将循环遍历您在该位置提供的路径C:\Temp\DeleteDirectories并将其删除。

希望这可以帮助!

相关内容