【问题标题】:Removing duplicate files with Powershell使用 Powershell 删除重复文件
【发布时间】:2020-03-01 01:02:03
【问题描述】:

我有几千个重复文件(例如 jar 文件),我想使用 powershell 来处理

  1. 递归搜索文件系统
  2. 查找副本(仅通过名称或校验和方法或两者)
  3. 删除除一个以外的所有重复项。

我是 powershell 的新手,我把它扔给那些可能能提供帮助的 PS 人。

【问题讨论】:

    标签: powershell


    【解决方案1】:

    试试这个:

    ls *.txt -recurse | get-filehash | group -property hash | where { $_.count -gt 1 } | % { $_.group | select -skip 1 } | del
    

    来自:http://n3wjack.net/2015/04/06/find-and-delete-duplicate-files-with-just-powershell/

    【讨论】:

      【解决方案2】:

      保留一个文件字典,当之前已经遇到下一个文件名时删除:

      $dict = @{};
      dir c:\admin -Recurse | foreach {
        $key = $_.Name #replace this with your checksum function
        $find = $dict[$key];
        if($find -ne $null) {
          #current file is a duplicate
          #Remove-Item -Path $_.FullName ?    
        }
        $dict[$key] = 0; #dummy placeholder to save memory
      }
      

      我使用文件名作为密钥,但您可以根据需要使用校验和(或两者都使用) - 请参阅代码注释。

      【讨论】:

      • 一个数组和一个-contains 检查就足够了。不需要字典。
      • @AnsgarWiechers:许多文件的性能问题?我的意思是它每次都需要逐个迭代数组,并且每一步都需要重新创建数组,对吧?
      • 我会将所有值放在 $dict = @{} 的花括号中,用逗号分隔?示例:@{one.jar, two.jar}
      • @notec:不知道你为什么想要那个,因为你的列表是动态的。不,您需要为每个指定值 - 哈希表是一个键值对。见this link
      • @Neolisk - 我运行了你的脚本。我看到它找到了所有重复并为每个重复分配零值。我现在如何删除未分配零值的重复项?我看到你有一个 Remove-Item 行注释掉了管道对象 FullName 受到质疑。感谢您让我走到这一步。
      【解决方案3】:

      尽管问题很老,但我一直需要根据内容清理所有重复文件。这个想法很简单,这个算法并不简单。这是接受“路径”参数以从中删除重复项的代码。

       Function Delete-Duplicates {
          param(
          [Parameter(
          Mandatory=$True,
          ValueFromPipeline=$True,
          ValueFromPipelineByPropertyName=$True
          )]
          [string[]]$PathDuplicates)
      
          $DuplicatePaths = 
              Get-ChildItem $PathDuplicates | 
              Get-FileHash |
              Group-Object -Property Hash |
              Where-Object -Property Count -gt 1 |
              ForEach-Object {
                  $_.Group.Path |
                  Select -First ($_.Count -1)}
          $TotalCount = (Get-ChildItem $PathDuplicates).Count
       Write-Warning ("You are going to delete {0} files out of {1} total. Please confirm the prompt" -f $DuplicatePaths.Count, $TotalCount)    
       $DuplicatePaths | Remove-Item -Confirm
      
          }
      

      脚本

      a) 列出所有 ChildItems

      b) 从它们中检索 FileHash

      c) 按哈希属性对它们进行分组(因此所有相同的文件都在一个组中)

      d) 过滤掉已经唯一的文件(组计数 -eq 1)

      e) 遍历每个组并列出除最后一个路径之外的所有路径 - 确保每个“哈希”的一个文件始终保留

      f) 之前的警告,说明总共有多少文件以及将要删除多少。

      可能不是最符合性能的选项(对每个文件进行 SHA1 处理),但可以确保文件是重复的。 对我来说非常好:)

      【讨论】:

        【解决方案4】:

        您可以用快捷方式替换,而不仅仅是删除重复文件

        #requires -version 3
        <#
            .SYNOPSIS
            Script de nettoyage des doublons
            .DESCRIPTION
            Cherche les doublons par taille, compare leur CheckSum MD5 et les regroupes par Taille et MD5
            peut remplacer chacun des doubles par un lien vers le 1er fichier, l'original
        
            .PARAMETER Path
            Chemin ou rechercher les doublon
        
            .PARAMETER ReplaceByShortcut
            si specifier alors les doublons seront remplacé
        
            .PARAMETER MinLength
            ignore les fichiers inferieure a cette taille (en Octets)
        
            .EXAMPLE
            .\Clean-Duplicate '\\dfs.adds\donnees\commun'
        
            .EXAMPLE
            recherche les doublon de 10Ko et plus
            .\Clean-Duplicate '\\dfs.adds\donnees\commun' -MinLength 10000
        
            .EXAMPLE
            .\Clean-Duplicate '\\dpm1\d$\Coaxis\Logiciels' -ReplaceByShortcut
        #>
        [CmdletBinding()]
        param (
            [string]$Path = '\\Contoso.adds\share$\path\data',
            [switch]$ReplaceByShortcut = $false,
            [int]$MinLength = 10*1024*1024 # 10 Mo
        )
        
        $version = '1.0'
        
        function Create-ShortCut ($ShortcutPath, $shortCutName, $Target) {
            $link = "$ShortcutPath\$shortCutName.lnk"
            $WshShell = New-Object -ComObject WScript.Shell
            $Shortcut = $WshShell.CreateShortcut($link)
            $Shortcut.TargetPath = $Target
            #$Shortcut.Arguments ="shell32.dll,Control_RunDLL hotplug.dll"
            #$Shortcut.IconLocation = "hotplug.dll,0"
            $Shortcut.Description ="Copy Doublon"
            #$Shortcut.WorkingDirectory ="C:\Windows\System32"
            $Shortcut.Save()
            # write-host -fore Cyan $link -nonewline; write-host -fore Red ' >> ' -nonewline; write-host -fore Yellow $Target 
            return $link
        }
        
        function Replace-ByShortcut {
            Param(
                [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
                    $SameItems
            )
            begin{
                $result = [pscustomobject][ordered]@{
                    Replaced = @()
                    Gain = 0
                    Count = 0
                }
            }
            Process{
                $Original = $SameItems.group[0]
                foreach ($doublon in $SameItems.group) {
                    if ($doublon -ne $Original) {
                        $result.Replaced += [pscustomobject][ordered]@{
                            lnk = Create-Shortcut -ShortcutPath $doublon.DirectoryName -shortCutName $doublon.BaseName -Target $Original.FullName
                            target = $Original.FullName
                            size = $doublon.Length
                        }
                        $result.Gain += $doublon.Length
                        $result.Count++
                        Remove-item $doublon.FullName -force
                    }
                }
            }
            End{
                $result
            }
        }
        
        function Get-MD5 {
            param (
                [Parameter(Mandatory)]
                    [string]$Path
            )
            $HashAlgorithm = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
            $Stream = [System.IO.File]::OpenRead($Path)
            try {
                $HashByteArray = $HashAlgorithm.ComputeHash($Stream)
            } finally {
                $Stream.Dispose()
            }
        
            return [System.BitConverter]::ToString($HashByteArray).ToLowerInvariant() -replace '-',''
        }
        
        if (-not $Path) {
            if ((Get-Location).Provider.Name -ne 'FileSystem') {
                Write-Error 'Specify a file system path explicitly, or change the current location to a file system path.'
                return
            }
            $Path = (Get-Location).ProviderPath
        }
        
        $DuplicateFiles = Get-ChildItem -Path $Path -Recurse -File |
            Where-Object { $_.Length -gt $MinLength } |
                Group-Object -Property Length |
                    Where-Object { $_.Count -gt 1 } |
                        ForEach-Object {
                            $_.Group |
                                ForEach-Object {
                                    $_ | Add-Member -MemberType NoteProperty -Name ContentHash -Value (Get-MD5 -Path $_.FullName)
                                }
                            $_.Group |
                                Group-Object -Property ContentHash |
                                    Where-Object { $_.Count -gt 1 }
                        }
        
        $somme = ($DuplicateFiles.group | Measure-Object length -Sum).sum
        write-host "$($DuplicateFiles.group.count) doublons, soit $($somme/1024/1024) Mo" -fore cyan
        
        if ($ReplaceByShortcut) {
            $DuplicateFiles | Replace-ByShortcut
        } else {
            $DuplicateFiles
        }
        

        【讨论】:

          猜你喜欢
          • 2023-03-27
          • 2021-10-05
          • 2018-04-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-05
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多