Показать полную графическую версию : [решено] Сравнение файлов в каталогах.
NikolayHAOS
11-11-2013, 11:07
Всем доброго времени суток.
Прочитал все похожие темы. но сам что-то дотумкать немогу. Потому прошу о помощи.
Есть два каталога с файлами. например D:\1 и D:\2.
Нужно сравнить файлы из 1 и 2 между собой и удалить все одинаковые из каталога 2
Файлы маленькие по размеру, если возможно сравнение по CRC или MD5, то вообще отлично.
PowerShell 3.0 и выше:
Function Get-FileHash
{
[CmdletBinding(DefaultParameterSetName = "Path")]
param(
[Parameter(Mandatory, ParameterSetName="Path", Position = 0)]
[System.String[]]
$Path,
[Parameter(Mandatory, ParameterSetName="LiteralPath", ValueFromPipelineByPropertyName = $true)]
[Alias("PSPath")]
[System.String[]]
$LiteralPath,
[ValidateSet("SHA1", "SHA256", "SHA384", "SHA512", "MACTripleDES", "MD5", "RIPEMD160")]
[System.String]
$Algorithm="SHA256"
)
begin
{
# Construct the strongly-typed crypto object
$hasher = [System.Security.Cryptography.HashAlgorithm]::Create($Algorithm)
}
process
{
$pathsToProcess = @()
if($PSCmdlet.ParameterSetName -eq "LiteralPath")
{
$pathsToProcess += Resolve-Path -LiteralPath $LiteralPath | Foreach-Object ProviderPath
}
else
{
$pathsToProcess += Resolve-Path $Path | Foreach-Object ProviderPath
}
foreach($filePath in $pathsToProcess)
{
if(Test-Path -LiteralPath $filePath -PathType Container)
{
continue
}
try
{
# Read the file specified in $FilePath as a Byte array
[system.io.stream]$stream = [system.io.file]::OpenRead($FilePath)
# Compute file-hash using the crypto object
[Byte[]] $computedHash = $hasher.ComputeHash($stream)
}
catch [Exception]
{
$errorMessage = [Microsoft.PowerShell.Commands.UtilityResources]::FileReadError -f $FilePath, $_
Write-Error -Message $errorMessage -Category ReadError -ErrorId "FileReadError" -TargetObject $FilePath
return
}
finally
{
if($stream)
{
$stream.Close()
}
}
# Convert to hex-encoded string
[string] $hash = [BitConverter]::ToString($computedHash) -replace '-',''
$retVal = [PSCustomObject] @{
Algorithm = $Algorithm.ToUpperInvariant()
Hash = $hash
Path = $filePath
}
$retVal.psobject.TypeNames.Insert(0, "Microsoft.Powershell.Utility.FileHash")
$retVal
}
}
}
Get-ChildItem D:\1,D:\2 -File | Select Name,FullName,@{n="Hash";e={(Get-FileHash $_.FullName -Algorithm MD5).Hash}} |
Group Name,Hash | Where Count -ge 2 | Remove-Item -Path {$_.Group.FullName -match "D:\\2\\"}
NikolayHAOS
11-11-2013, 12:15
Стесняюсь спросить а как этим пользоваться?
Скопировал содержимое в тестовой файл. Поставил расширение BAT и не чего не происходит.
ая-яй в названии темы не то указано, нужно было CMD/BAT.
Приношу свои извинения, видать что-то глюкнуло. Прошу модераторов отредактировать название, так как мне это уже не доступно.
Поставил расширение BAT »
Расширение — «.ps1». Должен быть установлен PowerShell 3.0 (включён в комплект Windows Management Framework 3.0 (http://www.microsoft.com/en-us/download/details.aspx?id=34595); требуется ОС не ниже Windows 7 SP1) и разрешено исполнение локальных скриптов PowerShell (Using the Set-ExecutionPolicy Cmdlet (http://technet.microsoft.com/en-us/library/ee176961.aspx)).
ая-яй в названии темы не то указано, нужно было CMD/BAT. »
NikolayHAOS, cmd/bat — это что-то из области садомазохизма. Лучше берите ClonesSpy (http://www.clonespy.com/) и задавайте ему параметры из пакетного файла.
NikolayHAOS
11-11-2013, 14:10
Так... понятно. Спасибо что помогаешь.
Вот что получаю при выполнении.
блин косяк какой то немогу перейти на диск D:\
http://img-fotki.yandex.ru/get/5008/78641505.0/0_d8594_e26afc1c_S.png (http://img-fotki.yandex.ru/get/5008/78641505.0/0_d8594_e26afc1c_orig)
Создал папку на диске C:\ вот что получил.
http://img-fotki.yandex.ru/get/9092/78641505.0/0_d8595_ffbd0745_XL.png (http://img-fotki.yandex.ru/get/9092/78641505.0/0_d8595_ffbd0745_orig)
Скрип не менял папки 1 и 2 созданы в корне диска D.
В них находятся одинаковые файлы, из папки 2 нечего не удалилось.
NikolayHAOS
11-11-2013, 14:29
В принципе хрен с ним с хешем, а если сравнивать по размеру например.
Вроде в Bat можно так сделать,
Получается: как сравнить содержимое двух папок, файлы по размеру, и удалить одинаковые в одной из них.
NikolayHAOS, Вам действительно нужен именно скрипт? Для автоматизации, не одноразовое действие?
Гуллипут
11-11-2013, 23:40
for %%f in (d:\2\*.*) do (
fc "%%f" "d:\1\%%~nxf"|find "FC: различия не найдены"
if not errorlevel 1 del "%%f"
)
Это сравнит по содержимому. Только файл должен создаваться в кодировке 866 (она же ASCII, она же DOS, она же OEM).
Если достаточно проверки по размеру, то изменим вот так:
for %%f in (d:\2\*.*) do (
for %%F in ("d:\1\%%~nxf") do if %%~zf==%%~zF del "%%f"
)
Это сравнит по содержимому. »
Гуллипут, вот это я и называю садомазохизмом ;).
NikolayHAOS
12-11-2013, 06:56
Iska, да скрипт, если бы один раз, то и вручную можно сравнить.
Есть набор файлов содержимое которых обновляется время от времени, но не всех сразу, задача быстренько отсеять не изменившиеся, до того как обратился на форум сравнивал через просмотр в архиваторе :o , там CRC считается.
Гуллипут кодировка UTF-8, второй вариант (по размеру) отлично отработал, НО какова вероятность изменения файла с сохранением изначального размера? вот и я думаю, а вдруг.
Мобыть кто-то может подсказать почему скрипт, предложенный Kazun, не срабатывает?
НО какова вероятность изменения файла с сохранением изначального размера? »
NikolayHAOS, Вы неправильно ставите вопрос. Любая ненулевая вероятность совпадения ставит жирный крест на использовании такого метода. Даже в случае MD5 она не нулевая (хоть и весьма, весьма низкая), а уж при попытках основывать отбор посредством сравнения по размерам… Даже не пытайтесь делать отсев файлов по такому слабому критерию — чревато печальными последствиями.
NikolayHAOS
12-11-2013, 08:54
Iska, Абсолютно согласен с вами.
Как правильно запустить скрипт, подскажите пожалуйста. Бьюсь бьюсь весь инет перерыл, ан нет все равно ошибка, мобыть в скрипте чего не так?
Выше я написал и тов. Iska дал ссылку, что требуется версия PowerShell 3.0 и выше.
Посмотреть версию PowerShell - $PSVersionTable.PSVersion
NikolayHAOS
12-11-2013, 14:49
Kazun, Агромное спасибо вы просто гений, все заработало.
Iska, Почему то считал что Framework 3.0 включен в 4.5.1 - ошибся. Установил и все отлично.
чревато печальными последствиями. »
И не говорите, подредактировал файл, поставил знак вопроса заместо точки, размер тот же, а вот хеш нет :-)
Всем агромное спасибо.
З.Ы. Жаль, что сам нефига не понимаю в этом скрипте, ща попробую изменить пути на свои. И отпишу.
Все работает. Благодарю.
Гуллипут
12-11-2013, 19:24
NikolayHAOS, я говорил про кодировку самого bat-файла. Кодировка сравниваемых файлов безразлична. Они могут быть даже двоичные, только надо добавить после команды fc ключ /b:
for %%f in (d:\2\*.*) do (
fc /b "%%f" "d:\1\%%~nxf"|find "FC: различия не найдены"
if not errorlevel 1 del "%%f"
)
Iska, по крайней мере, это решение значительно компактнее, чем то, что предложил Kazun.
Поскольку bat - это язык файло-ориентированный, многие операции над файлами в нём программируются намного проще, чем в других. Поэтому я не считаю это садомазохизмом. :tongue:
Гуллипут, дело, разумеется, не в Вашем коде, а в особенностях сравнения «fc.exe»: в общем случае сравнение по хэшам выигрывает в производительности.
NikolayHAOS
13-11-2013, 00:05
Гуллипут, Спасибо и ваш метод отлично работает, И в мне легче разобраться в вашем коде, так как его почти там нет :-).
Гуллипут
13-11-2013, 07:50
Гуллипут, дело, разумеется, не в Вашем коде, а в особенностях сравнения «fc.exe»: в общем случае сравнение по хэшам выигрывает в производительности. »
Сомневаюсь. Ведь для вычисления хэша надо всё равно прочитать весь файл. Выигрыш только за счёт операций сравнения, зато вычисление хэша занимает больше времени, чем просто чтение строк из файла. Хэш полезен в случае, когда он вычисляется каждый раз при изменении хэшируемого объекта, с тем, чтобы в дальнейшем при сравнении уже сравнивать только хэши. То есть затраты времени "распределяются" более равномерно.
Правда, я не разбирался в алгоритме, который выложил Kazun, может, он так и делает ? Но для этого ему надо ставить обработчик на событие изменения файлов в каталоге. В принципе, реально, я это делал на Delphi, но не знаю, может ли это PowerShell. В нём я не разбираюсь: пару лет назад проглядел одну книжку, но на работе это не используется, поэтому и благополучно забыл прочитанное.
Сомневаюсь. Ведь для вычисления хэша надо всё равно прочитать весь файл. »
Гуллипут, для сравнения — тоже. И, в отличие от сравнения по хэшам, читать, в случае сравнения MxN файлов, каждый из M придётся в худшем случае ровно N раз (вместо одного раза). И так же читать M раз каждый из N файлов. Вот почему «fc.exe» хуже подходит сравнения по хэшам. Можно предварительно сравнивать по размерам, это, в общем случае, даст заметную экономию. Но именно в некоем «общем случае», а сравнение ведь, как правило, проводится отнюдь не для неких усреднённых «общих случаев», а конкретно там, где заранее предполагается наличие какого-то числа одинаковых файлов.
CloneSpy умеет работать с предварительно рассчитанными им и сохранёнными наборами хэшей файлов. Это удобно в случае, аналогичном рассматриваемому — когда неизменный или редко обновляемый набор файлов сравнивается со вновь поступающими наборами файлов.
Гуллипут
18-11-2013, 21:56
Iska, я сравниваю не каждый файл с каждым, а файлы с совпадающими именами. Поскольку "одинаковость файлов" я понял, как совпадение не только содержимого, но и имён.
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.