Differences
This shows you the differences between the selected revisions of the page.
2016-09-29 | 2016-09-29 | ||
typo (martin) | reimplemeting using EnumerateRemoteFiles and FullName (martin) | ||
Line 18: | Line 18: | ||
# @description Searches for duplicate files on the server, starting from the current directory | # @description Searches for duplicate files on the server, starting from the current directory | ||
# @flag RemoteFiles | # @flag RemoteFiles | ||
- | # @version 2 | + | # @version 3 |
- | # @homepage ~~SELF~~ | + | # @homepage https://winscp.net/eng/docs/library_example_find_duplicate_files |
- | # @require WinSCP 5.8.4 | + | # @require WinSCP 5.9.1 |
# @option RemoteChecksumAlg -config -run combobox "&Checksum:" "local" "local=Local sha-1" "sha1=Remote sha-1" "sha256=Remote sha-256" "md5=Remote md5" | # @option RemoteChecksumAlg -config -run combobox "&Checksum:" "local" "local=Local sha-1" "sha1=Remote sha-1" "sha256=Remote sha-256" "md5=Remote md5" | ||
# @option SessionLogPath -config sessionlogfile | # @option SessionLogPath -config sessionlogfile | ||
- | # @optionspage ~~SELF~~#options | + | # @optionspage https://winscp.net/eng/docs/library_example_find_duplicate_files#options |
+ | · | ||
param ( | param ( | ||
# Use Generate URL function to obtain a value for -sessionUrl parameter. | # Use Generate URL function to obtain a value for -sessionUrl parameter. | ||
Line 35: | Line 35: | ||
$pause = $False | $pause = $False | ||
) | ) | ||
+ | · | ||
function FileChecksum ($remotePath) | function FileChecksum ($remotePath) | ||
{ | { | ||
Line 46: | Line 46: | ||
$localPath = [System.IO.Path]::GetTempFileName() | $localPath = [System.IO.Path]::GetTempFileName() | ||
$transferResult = $session.GetFiles($remotePath, $localPath) | $transferResult = $session.GetFiles($remotePath, $localPath) | ||
+ | · | ||
if ($transferResult.IsSuccess) | if ($transferResult.IsSuccess) | ||
{ | { | ||
Line 54: | Line 54: | ||
Write-Host ("Downloaded file {0} checksum is {1}" -f $remotePath, $checksum) | Write-Host ("Downloaded file {0} checksum is {1}" -f $remotePath, $checksum) | ||
+ | · | ||
Remove-Item $localPath | Remove-Item $localPath | ||
} | } | ||
Line 69: | Line 69: | ||
Write-Host ("File {0} checksum is {1}" -f $remotePath, $checksum) | Write-Host ("File {0} checksum is {1}" -f $remotePath, $checksum) | ||
} | } | ||
+ | · | ||
$checksums[$remotePath] = $checksum | $checksums[$remotePath] = $checksum | ||
} | } | ||
+ | · | ||
return $checksums[$remotePath] | return $checksums[$remotePath] | ||
- | } | ||
- | |||
- | function FindDuplicatesInDirectory ($remotePath) | ||
- | { | ||
- | Write-Host ("Finding duplicates in directory {0} ..." -f $remotePath) | ||
- | |||
- | try | ||
- | { | ||
- | $directoryInfo = $session.ListDirectory($remotePath) | ||
- | |||
- | foreach ($fileInfo in $directoryInfo.Files) | ||
- | { | ||
- | $remoteFilePath = $session.CombinePaths($remotePath, $fileInfo.Name) | ||
- | |||
- | if ($fileInfo.IsDirectory) | ||
- | { | ||
- | # Skip references to current and parent directories | ||
- | if (($fileInfo.Name -ne ".") -and | ||
- | ($fileInfo.Name -ne "..")) | ||
- | { | ||
- | # Recurse into subdirectories | ||
- | FindDuplicatesInDirectory $remoteFilePath | ||
- | } | ||
- | } | ||
- | else | ||
- | { | ||
- | Write-Host ("Found file {0} with size {1}" -f $remoteFilePath, $fileInfo.Length) | ||
- | |||
- | if ($sizes.ContainsKey($fileInfo.Length)) | ||
- | { | ||
- | $checksum = FileChecksum($remoteFilePath) | ||
- | |||
- | foreach ($otherFilePath in $sizes[$fileInfo.Length]) | ||
- | { | ||
- | $otherChecksum = FileChecksum($otherFilePath) | ||
- | |||
- | if ($checksum -eq $otherChecksum) | ||
- | { | ||
- | Write-Host ("Checksums of files {0} and {1} are identical" -f $remoteFilePath, $otherFilePath) | ||
- | $duplicates[$remoteFilePath] = $otherFilePath | ||
- | } | ||
- | } | ||
- | } | ||
- | else | ||
- | { | ||
- | $sizes[$fileInfo.Length] = @() | ||
- | } | ||
- | |||
- | $sizes[$fileInfo.Length] += $remoteFilePath | ||
- | } | ||
- | } | ||
- | } | ||
- | catch [Exception] | ||
- | { | ||
- | Write-Host ("Error processing directory {0}: {1}" -f $remotePath, $_.Exception.Message) | ||
- | } | ||
} | } | ||
Line 147: | Line 91: | ||
{ | { | ||
$session.SessionLogPath = $sessionLogPath | $session.SessionLogPath = $sessionLogPath | ||
+ | · | ||
# Connect | # Connect | ||
$session.Open($sessionOptions) | $session.Open($sessionOptions) | ||
+ | # Handle errors when enumerating the files | ||
+ | $session.add_Failed( { | ||
+ | Write-Host ("Error: {0}" -f $_.Error.Message) | ||
+ | } ) | ||
+ | |||
$sizes = @{} | $sizes = @{} | ||
$checksums = @{} | $checksums = @{} | ||
Line 156: | Line 105: | ||
$sha1 = [System.Security.Cryptography.SHA1]::Create() | $sha1 = [System.Security.Cryptography.SHA1]::Create() | ||
+ | |||
+ | $files = $session.EnumerateRemoteFiles($remotePath, "*", [WinSCP.EnumerationOptions]::AllDirectories) | ||
- | # Start recursion | + | foreach ($fileInfo in $files) |
- | FindDuplicatesInDirectory $remotePath | + | { |
+ | Write-Host ("Found file {0} with size {1}" -f $fileInfo.FullName, $fileInfo.Length) | ||
+ | |||
+ | if ($sizes.ContainsKey($fileInfo.Length)) | ||
+ | { | ||
+ | $checksum = FileChecksum($fileInfo.FullName) | ||
+ | |||
+ | foreach ($otherFilePath in $sizes[$fileInfo.Length]) | ||
+ | { | ||
+ | $otherChecksum = FileChecksum($otherFilePath) | ||
+ | |||
+ | if ($checksum -eq $otherChecksum) | ||
+ | { | ||
+ | Write-Host ("Checksums of files {0} and {1} are identical" -f $fileInfo.FullName, $otherFilePath) | ||
+ | $duplicates[$fileInfo.FullName] = $otherFilePath | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | $sizes[$fileInfo.Length] = @() | ||
+ | } | ||
+ | |||
+ | $sizes[$fileInfo.Length] += $fileInfo.FullName | ||
+ | } | ||
} | } | ||
finally | finally | ||
Line 165: | Line 140: | ||
$session.Dispose() | $session.Dispose() | ||
} | } | ||
+ | · | ||
# Print results | # Print results | ||
Write-Host | Write-Host | ||
+ | · | ||
if ($duplicates.Count -gt 0) | if ($duplicates.Count -gt 0) | ||
{ | { | ||
Write-Host "Duplicates found:" | Write-Host "Duplicates found:" | ||
+ | · | ||
foreach ($path1 in $duplicates.Keys) | foreach ($path1 in $duplicates.Keys) | ||
{ | { | ||
Line 182: | Line 157: | ||
Write-Host "No duplicates found." | Write-Host "No duplicates found." | ||
} | } | ||
+ | · | ||
$result = 0 | $result = 0 | ||
} | } | ||
Line 197: | Line 172: | ||
[System.Console]::ReadKey() | Out-Null | [System.Console]::ReadKey() | Out-Null | ||
} | } | ||
+ | · | ||
exit $result | exit $result | ||
</code> | </code> |