【问题标题】:Powershell renaming files recursively, not renaming duplicatesPowershell递归重命名文件,而不是重命名重复项
【发布时间】:2017-03-08 16:40:35
【问题描述】:

我有一些 powershell 代码,旨在递归地从文件名中取出特定字符。这很好用,除非取出字符会导致 2 个文件与同一文件夹中的名称匹配。

我在这里找到了 Powershell PowerShell script to remove characters from files and folders,但它并没有解决我遇到的问题。

$characters = "$#"
$regex = "[$([regex]::Escape($characters))]"

$filesandfolders = Get-ChildItem -recurse "D:\projects\filenameCleaner\TEST" | Where-Object {$_.name -match $regex} 
$filesandfolders | Where-Object {!$_.PsIscontainer}  |  foreach {
    $New=$_.name -Replace $regex
    Rename-Item -path $_.Fullname -newname $New -passthru
}
$filesandfolders | Where-Object {$_.PsIscontainer}  |  foreach {
    $New=$_.name -Replace $regex
    Rename-Item -path $_.Fullname -newname $New -passthru
}

我还不是很精通 Powershell,希望能得到一些帮助。我只想要脚本,如果它发现重复,它应该在最后添加 (1) 或 (2) 等,具体取决于有多少。

请不要只给我一个答案,请解释一下,以便我了解正在发生的事情

【问题讨论】:

    标签: powershell recursion


    【解决方案1】:

    我认为解决这个问题的方法是创建一个包含源路径和目标路径的新 PSOBJECT。然后,您可以使用 Group-object 在目标路径上进行分组,这将为您提供一个计数,然后您可以使用该计数来确定哪些文件需要数字后缀。

    类似这样的:

    Get-ChildItem -recurse "D:\projects\filenameCleaner\TEST" | ? {!$_.PsIscontainer} | % {
        New-Object psobject -Property @{
            source = $_.FullName
            target = ($_.FullName -replace [regex]::Escape($_.Name)) + ($_.Name -replace '[\$#]+', '') 
        }
    } | Group-Object target | % {
        $g = $_.Group
        0..($g.Count - 1) | % {
            New-Object psobject -Property @{
                source = $g[$_].source
                target = $g[$_].target -replace '\.',  @('.', "($($_)).")[$_ -gt 0]
            }        
        }
    } | % {Rename-Item -Path $_.source -NewName $_.Target}
    

    这样做的好处是它可以重复两个、三个或更多

    我只完成了文件的代码,所以你需要另一个版本的文件夹。

    【讨论】:

    • 谢谢,但这看起来比我需要的复杂得多。我完全不确定这是如何工作的
    • 我认为了解它在做什么的方法是运行它的部分并研究输出。首先从头开始运行到Group-Object 之前的管道之前,然后从头开始运行,但包括Group-object。代码将您的问题分解为多个步骤,每个步骤都成为链上的管道。想想这样的步骤 1) 获取文件列表 2) 删除文件夹 3) 捕获文件路径和新文件路径 4) 新文件路径上的组并计算重复项 5) 遍历组并添加计数如果需要 6) 重命名文件。对我来说听起来很简单。
    • 非常好的方法 Dave,我发现以前运行的重复项存在问题,这些重复项不会包含在组中。
    • 好点 - 我想解决这个问题的简单方法是在第一个 PSOBJECT 中捕获目标路径时去掉括号和数字,以便文件恢复到原来的分组,一些像-replace '\(\d+\)\.', '.' 应该这样做。这意味着某些重复项会被重新编号,但我认为这不是问题。
    【解决方案2】:

    我可以通过添加一个检查新路径的 if 语句来做到这一点

    $characters = "$#}"
    $regex = "[$([regex]::Escape($characters))]"
    $path = "D:\projects\filenameCleaner\TEST"
    $filesandfolders = Get-ChildItem -recurse $path | Where-Object {$_.name -match $regex} 
    $filesandfolders | Where-Object {!$_.PsIscontainer}  |  foreach {
        $New=$_.name -Replace $regex
        $newPath = $path+"\"+$New
        $loop = 0
        while (Test-Path $newPath) {
            $loop = $loop + 1
            $basename = $_.basename -Replace $regex
            $New = $basename + " ("+$loop+")"+$_.extension
            $newPath = $path+"\"+$New
        }
        "Rename `""+$_.name+"`" to `""+$New+"`""
        Rename-Item -path $_.Fullname -newname $New -passthru
    }
    $filesandfolders | Where-Object {$_.PsIscontainer}  |  foreach {
        $New=$_.name -Replace $regex
        $newPath = $path+"\"+$New
        $loop = 0
        while (Test-Path $newPath) {
            $loop = $loop + 1
            $basename = $_.basename -Replace $regex
            $New = $basename + " ("+$loop+")"+$_.extension
            $newPath = $path+"\"+$New
        }
        "Rename `""+$_.name+"`" to `""+$New+"`""
        Rename-Item -path $_.Fullname -newname $New -passthru
    }
    

    -- 另一个在将数字添加到重复字符串时单独处理扩展名的更新。我遇到的问题是数字会在扩展名之后进入文件名,这显然是不行的

    【讨论】:

    • 假设我在名为 d$#ata.csv、da$#ta.csv 和 dat$#a.csv 的文件夹中有三个文件 - 您的代码将如何处理?
    • @DaveSexton 你是完全正确的。我已经解决了我相信我的更新的问题,你还发现其他问题吗?
    • No 现在似乎很好。只是一般性评论,我认为您需要更多地了解 Powershell 的精神。在 Powershell 中,您拥有所有这些很酷的功能,例如管道、范围和字符串扩展。您不需要所有复杂的字符串连接。例如,您的输出行可以这样完成:"Rename `"$($_.name)`" to `"$New`"" 或其他类似的替代方案:'Rename "{0}" to "{1}"' -f $_.name, $New
    猜你喜欢
    • 2014-03-03
    • 2011-11-03
    • 2020-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-27
    • 1970-01-01
    相关资源
    最近更新 更多