Datei-Duplikate durch symbolische Links ersetzen

Ich hatte unter Windows 7 das Problem, dass ich einem Verzeichnis mit sehr vielen Dateien doppelte Dateien finden wollte, um diese dann durch symbolische Links zu ersetzen. Zum identifizieren von Datei-Duplikaten habe ich das Programm Dupfinder verwendet.

Dieses identifziert Datei-Duplikate zuverlässig und schnell. Außerdem kann es  symbolische Links für die identifizierten Duplikate anlegen. Der Nachteil ist, dass dies nicht funktioniert, wenn zu mehreren Dateien Duplikate gefunden wurden.

[singlepic id=14 w=340 h=290 float=]

Diese Problem verdeutlicht der Screenshot. Um den gewünschten Effekt zu erzielen müsste man zunächst die Dateien der ersten Gruppe und dann die der zweiten Gruppe markieren. Wenn viele Gruppen von Duplikaten gefunden wurden, kann das echt mühselig werden.

Deshalb habe ich ein kleines Powershell-Skript geschrieben, um diesen Job zu erledigen. Basis für dieses bildet die Ausgabe des DupFinder Kommandzeilen-Tools dupf.

Das Skript erwartete die Ausgabe von dupf im Verzeichnis d:temp in einer Datei mit dem Namen dups.txt. Diese ist – wenn Duplikate gefunden wurden – aus einem oder mehreren Blöcken aufgebaut, die wie folgt aussehen.

- 3 equal files of size 1283065
    "c:somepathorg.txt"
    "c:otherpathduplicate 1.txt"
    "c:otherpath2duplicate.txt"

Die Dateien ab Zeile zwei werden als Duplikate betrachtet.
Die erste Datei bleibt erhalten und die beiden anderen werden durch symbolische Links auf diese ersetzt.

[sourcecode language=“powershell“]
function Pause ($Message="Press any key to continue…") {
Write-Host -NoNewLine $Message
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
Write-Host ""
}

#
# Adminrechte besorgen
#
$id=[System.Security.Principal.WindowsIdentity]::GetCurrent()
$principal=New-Object System.Security.Principal.WindowsPrincipal($id)
if(!$principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)) {
$powershell=[System.Diagnostics.Process]::GetCurrentProcess()
$psi=New-Object System.Diagnostics.ProcessStartInfo $powershell.Path
$script=$MyInvocation.MyCommand.Path
$prm=$script
foreach($a in $args) {
$prm+=‘ ‚+$a
}
$psi.Arguments=$prm
$psi.Verb="runas"
[System.Diagnostics.Process]::Start($psi) | Out-Null
return;
}

#
# Ab hier mit Adminrechtn
#
$reader = [System.IO.File]::OpenText("d:tempdups.txt")
try {
for(;;) {
$line = $reader.ReadLine()
if ($line -eq $null) { break }
if( $line.StartsWith("-") )
{
$elements = $line.split(" ")
$count = $elements[1]
$org = $reader.ReadLine()
for( $i = 1; $i -lt $count; $i++ )
{
$dup = $reader.ReadLine() -replace ‚"‘
&del -path $dup
$params = @($dup, $org)
&cmd /c mklink $params
}
}
}
}
finally {
$reader.Close()
}

Pause
[/sourcecode]

ACHTUNG: Zum setzen der symbolischen Links werden Adminrechte benötigt, die sich das Skript selbstständig besorgt.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.