我有数百个文件,其路径长度超过 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
答案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
并将其删除。
希望这可以帮助!