Поиск дубликатов файлов с помощью PowerShell

Для одного из проектов нам понадобился PowerShell скрипт, который бы находил дубликаты файлов в сетевых папках сервера. Для Windows есть большое количество утилит для поиска и удаления дубликатов файлов, однако большинство из них платные либо слабо подходят для автоматизации.

Так как у файлов могут быть разные имена, но идентичное содержимое, некорректно будет сравнивать файлы просто по именам. Лучше получить хэши всех файлов и найти среди них одинаковые.

Следующий однострочный PowerShell скрипт позволяет рекурсивно просканировать указанную папку (включая вложенные) и найти дубликаты файлов. В данном примере нашлись два файла одинаковых файла с идентичными хэшами:

Get-ChildItem –path C:\Share\ -Recurse | Get-FileHash | Group-Object -property hash | Where-Object { $_.count -gt 1 } | ForEach-Object { $_.group | Select-Object Path, Hash }

поиск дубликатов файлов в windows с помощью PowerShell

Такой однострочную команду PowerShell удобно использовать для поиска дубликатов, но производительность ее оставляет желать лучшего. Если файлов в каталоге много и для каждого считать хэш, это займет довольно много времени. Проще сначала сравнить файлы по размеру (это готовый атрибут файла, который не надо вычислять). Хэш будем получать только для файлов с одинаковым размером:

$file_dublicates = Get-ChildItem –path C:\Share\ -Recurse| Group-Object -property Length| Where-Object { $_.count -gt 1 }| Select-Object –Expand Group| Get-FileHash | Group-Object -property hash | Where-Object { $_.count -gt 1 }| ForEach-Object { $_.group | Select-Object Path, Hash }

Можете сравнить производительность обеих команда на тестовой папке с помощью Measure-Command:

Measure-Command {your_powershell_command}

На небольшом каталоге с 2000 файлов разница в скорости выполнения второй команды будет на несколько порядков быстрее (10 минут vs 3 секунды).

Можно предложить пользователю выбрать файлы, которые можно удалить. Для этого список дубликатов файлов нужно передать конвейером в командлет Out-GridView:

$file_dublicates | Out-GridView -Title "Выберите файлы для удаления" -OutputMode Multiple –PassThru|Remove-Item –Verbose –WhatIf

powershell скрипт для поиска и удаления дубликатов файлов

Пользователь в таблице может выбрать файлы для удаления (чтобы выбрать несколько файлов, нужно зажать ctrl) и нажать Ok.

Вместо удаления вы можете переместить выбранные файлы в другой каталог, с помощью Move-Item .

Вадим Стеркин в своем блоге www.outsidethebox.ms предлагает заменять дубликаты файлов на жесткие ссылки. Такой подход позволит сохранить файлы на месте и существенно сэкономить место на диске.

Приведу полный код скрипта с его сайта здесь (https://www.outsidethebox.ms/20953/):

param(
[Parameter(Mandatory=$True)]
[ValidateScript({Test-Path -Path $_ -PathType Container})]
[string]$dir1,
[Parameter(Mandatory=$True)]
[ValidateScript({(Test-Path -Path $_ -PathType Container) -and $_ -ne $dir1})]
[string]$dir2
)
Get-ChildItem -Recurse $dir1, $dir2 |
Group-Object Length | Where-Object {$_.Count -ge 2} |
Select-Object -Expand Group | Get-FileHash |
Group-Object hash | Where-Object {$_.Count -ge 2} |
Foreach-Object {
$f1 = $_.Group[0].Path
Remove-Item $f1
New-Item -ItemType HardLink -Path $f1 -Target $_.Group[1].Path | Out-Null
#fsutil hardlink create $f1 $_.Group[1].Path
}

Для запуска файла используйте такой формат команды:

.\hardlinks.ps1 -dir1 d:\fldr1 -dir2 d:\fldr2

Этот скрипт можно использовать для поиска и замены дубликатов статических файлов (которые не изменяются!) на символические жёсткие ссылки.

В Windows Server для радикального решения проблемы дубликатов файлов можно использовать встроенный компонент Data Deduplication роли File Server. Однако при использовании дедупликции и инкрементального бэкапа вы столкнетесь со сложностями при восстановлении.

Также для замены дубликатов файлов жесткими ссылками можно использовать консольную утилиту dupemerge.


Предыдущая статья Следующая статья


Комментариев: 4 Оставить комментарий

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Я не робот( Обязательно отметьте)