Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] Сравнение файлов в каталогах. (http://forum.oszone.net/showthread.php?t=271784)

NikolayHAOS 11-11-2013 11:07 2251856

Сравнение файлов в каталогах.
 
Всем доброго времени суток.
Прочитал все похожие темы. но сам что-то дотумкать немогу. Потому прошу о помощи.
Есть два каталога с файлами. например D:\1 и D:\2.
Нужно сравнить файлы из 1 и 2 между собой и удалить все одинаковые из каталога 2
Файлы маленькие по размеру, если возможно сравнение по CRC или MD5, то вообще отлично.

Kazun 11-11-2013 11:35 2251874

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 2251889

Стесняюсь спросить а как этим пользоваться?
Скопировал содержимое в тестовой файл. Поставил расширение BAT и не чего не происходит.

ая-яй в названии темы не то указано, нужно было CMD/BAT.
Приношу свои извинения, видать что-то глюкнуло. Прошу модераторов отредактировать название, так как мне это уже не доступно.

Iska 11-11-2013 12:37 2251900

Цитата:

Цитата NikolayHAOS
Поставил расширение BAT »

Расширение — «.ps1». Должен быть установлен PowerShell 3.0 (включён в комплект Windows Management Framework 3.0; требуется ОС не ниже Windows 7 SP1) и разрешено исполнение локальных скриптов PowerShell (Using the Set-ExecutionPolicy Cmdlet).

Цитата:

Цитата NikolayHAOS
ая-яй в названии темы не то указано, нужно было CMD/BAT. »

NikolayHAOS, cmd/bat — это что-то из области садомазохизма. Лучше берите ClonesSpy и задавайте ему параметры из пакетного файла.

NikolayHAOS 11-11-2013 14:10 2251974

Так... понятно. Спасибо что помогаешь.
Вот что получаю при выполнении.
блин косяк какой то немогу перейти на диск D:\

Создал папку на диске C:\ вот что получил.


Скрип не менял папки 1 и 2 созданы в корне диска D.
В них находятся одинаковые файлы, из папки 2 нечего не удалилось.

NikolayHAOS 11-11-2013 14:29 2251986

В принципе хрен с ним с хешем, а если сравнивать по размеру например.
Вроде в Bat можно так сделать,
Получается: как сравнить содержимое двух папок, файлы по размеру, и удалить одинаковые в одной из них.

Iska 11-11-2013 15:26 2252045

NikolayHAOS, Вам действительно нужен именно скрипт? Для автоматизации, не одноразовое действие?

Гуллипут 11-11-2013 23:40 2252447

Код:

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"
)


Iska 11-11-2013 23:56 2252450

Цитата:

Цитата Гуллипут
Это сравнит по содержимому. »

Гуллипут, вот это я и называю садомазохизмом ;).

NikolayHAOS 12-11-2013 06:56 2252532

Iska, да скрипт, если бы один раз, то и вручную можно сравнить.
Есть набор файлов содержимое которых обновляется время от времени, но не всех сразу, задача быстренько отсеять не изменившиеся, до того как обратился на форум сравнивал через просмотр в архиваторе :o , там CRC считается.
Гуллипут кодировка UTF-8, второй вариант (по размеру) отлично отработал, НО какова вероятность изменения файла с сохранением изначального размера? вот и я думаю, а вдруг.

Мобыть кто-то может подсказать почему скрипт, предложенный Kazun, не срабатывает?

Iska 12-11-2013 08:50 2252576

Цитата:

Цитата NikolayHAOS
НО какова вероятность изменения файла с сохранением изначального размера? »

NikolayHAOS, Вы неправильно ставите вопрос.
читать дальше »
Любая ненулевая вероятность совпадения ставит жирный крест на использовании такого метода. Даже в случае MD5 она не нулевая (хоть и весьма, весьма низкая), а уж при попытках основывать отбор посредством сравнения по размерам… Даже не пытайтесь делать отсев файлов по такому слабому критерию — чревато печальными последствиями.

NikolayHAOS 12-11-2013 08:54 2252578

Iska, Абсолютно согласен с вами.
Как правильно запустить скрипт, подскажите пожалуйста. Бьюсь бьюсь весь инет перерыл, ан нет все равно ошибка, мобыть в скрипте чего не так?

Kazun 12-11-2013 08:59 2252582

Выше я написал и тов. Iska дал ссылку, что требуется версия PowerShell 3.0 и выше.

Посмотреть версию PowerShell - $PSVersionTable.PSVersion

NikolayHAOS 12-11-2013 14:49 2252847

Kazun, Агромное спасибо вы просто гений, все заработало.
Iska, Почему то считал что Framework 3.0 включен в 4.5.1 - ошибся. Установил и все отлично.
Цитата:

Цитата Iska
чревато печальными последствиями. »

И не говорите, подредактировал файл, поставил знак вопроса заместо точки, размер тот же, а вот хеш нет :-)
Всем агромное спасибо.
З.Ы. Жаль, что сам нефига не понимаю в этом скрипте, ща попробую изменить пути на свои. И отпишу.

Все работает. Благодарю.

Гуллипут 12-11-2013 19:24 2253098

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:

Iska 12-11-2013 20:06 2253129

Гуллипут, дело, разумеется, не в Вашем коде, а в особенностях сравнения «fc.exe»: в общем случае сравнение по хэшам выигрывает в производительности.

NikolayHAOS 13-11-2013 00:05 2253321

Гуллипут, Спасибо и ваш метод отлично работает, И в мне легче разобраться в вашем коде, так как его почти там нет :-).

Гуллипут 13-11-2013 07:50 2253421

Цитата:

Цитата Iska
Гуллипут, дело, разумеется, не в Вашем коде, а в особенностях сравнения «fc.exe»: в общем случае сравнение по хэшам выигрывает в производительности. »

Сомневаюсь. Ведь для вычисления хэша надо всё равно прочитать весь файл. Выигрыш только за счёт операций сравнения, зато вычисление хэша занимает больше времени, чем просто чтение строк из файла. Хэш полезен в случае, когда он вычисляется каждый раз при изменении хэшируемого объекта, с тем, чтобы в дальнейшем при сравнении уже сравнивать только хэши. То есть затраты времени "распределяются" более равномерно.
Правда, я не разбирался в алгоритме, который выложил Kazun, может, он так и делает ? Но для этого ему надо ставить обработчик на событие изменения файлов в каталоге. В принципе, реально, я это делал на Delphi, но не знаю, может ли это PowerShell. В нём я не разбираюсь: пару лет назад проглядел одну книжку, но на работе это не используется, поэтому и благополучно забыл прочитанное.

Iska 17-11-2013 10:43 2256325

Цитата:

Цитата Гуллипут
Сомневаюсь. Ведь для вычисления хэша надо всё равно прочитать весь файл. »

Гуллипут, для сравнения — тоже. И, в отличие от сравнения по хэшам, читать, в случае сравнения MxN файлов, каждый из M придётся в худшем случае ровно N раз (вместо одного раза). И так же читать M раз каждый из N файлов. Вот почему «fc.exe» хуже подходит сравнения по хэшам. Можно предварительно сравнивать по размерам, это, в общем случае, даст заметную экономию. Но именно в некоем «общем случае», а сравнение ведь, как правило, проводится отнюдь не для неких усреднённых «общих случаев», а конкретно там, где заранее предполагается наличие какого-то числа одинаковых файлов.

CloneSpy умеет работать с предварительно рассчитанными им и сохранёнными наборами хэшей файлов. Это удобно в случае, аналогичном рассматриваемому — когда неизменный или редко обновляемый набор файлов сравнивается со вновь поступающими наборами файлов.

Гуллипут 18-11-2013 21:56 2257437

Iska, я сравниваю не каждый файл с каждым, а файлы с совпадающими именами. Поскольку "одинаковость файлов" я понял, как совпадение не только содержимого, но и имён.

kiripanda 18-11-2013 23:23 2257536

http://forum.wincmd.ru/viewpost.php?p=80462
вижу, можно улучшить: сначала найти группы одинаковых по размеру файлов,
и только их сравнивать по хешу (параноики могут сравнивать по содержимому ;)

для Total Commander http://wincmd.ru/plugring/DupSelector1001.html
Цитата:

Программа предназначена для выделения дубликатов файлов в панели с результатами поиска.

Iska 18-11-2013 23:37 2257545

kiripanda, я свой выбор давно сделал — это CloneSpy.


Время: 13:41.

Время: 13:41.
© OSzone.net 2001-