powershell を使用したい重複ファイル (例として jar ファイル) が数千あります。
- ファイルシステムを再帰的に検索する
- 重複を見つけます(名前のみ、チェックサム方式、またはその両方で)
- 1 つを除いてすべての重複を削除します。
私はpowershellが初めてで、これを助けてくれるかもしれないPSの人々に投げかけています。
powershell を使用したい重複ファイル (例として jar ファイル) が数千あります。
私はpowershellが初めてで、これを助けてくれるかもしれないPSの人々に投げかけています。
これを試して:
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/
質問は古いですが、コンテンツに基づいてすべての重複ファイルをクリーンアップする必要がありました。アイデアは単純ですが、このためのアルゴリズムは簡単ではありません。これは、重複を削除する「パス」のパラメーターを受け入れるコードです。
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)各グループをループし、最後のパスを除くすべてのパスをリストします-各「ハッシュ」の1つのファイルが常に残るようにします
f) 先行する前に、合計でいくつのファイルがあり、いくつのファイルが削除されるかを警告します。
おそらく最もパフォーマンス上のオプション (すべてのファイルを SHA1 で処理する) ではありませんが、ファイルが重複していることを保証します。私にとっては完璧に機能します:)
ファイルの辞書を保持し、次のファイル名が以前に見つかった場合は削除します。
$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
}
ファイル名をキーとして使用しましたが、必要に応じてチェックサムを使用できます (または両方) - コード コメントを参照してください。
重複ファイルを削除するだけでなく、ショートカットで置き換えることができます
#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
}