• XSS.stack #1 – первый литературный журнал от юзеров форума

cmd/bat распаковка архива с автоудалением после распаковки

SingleAdwice

(L1) cache
Пользователь
Регистрация
05.08.2020
Сообщения
508
Реакции
448
Депозит
0.0007
Сабж, требуется распаковать пару лямов архивов, чтобы каждый архив распаковался в папку с именем архива и затем исходный архив удалялся
если папка с таким именем уже существует и в ней уже есть файлы, то должна выполнятся перезапись

за решение накину 50$ на пиво
 
Решение
интересует решение задачи стандартными способами используя лишь средства вин
Ок. Powershell. А он же .NET. Заюзаем новомодные фичи, не малварь же пишем под все ОС. Таргет WIN 10, думаю уже все обновились?))
Powershell 5+.
The EnumerateFiles and GetFiles methods differ as follows: When you use EnumerateFiles, you can start enumerating the collection of names before the whole collection is returned; when you use GetFiles, you must wait for the whole array of names to be returned before you can access the array.
EnumerateFiles возвращает итератор. Таким образом можно осуществить lazy перебор файлов, не загружая список всех файлов в RAM. Просто лениво итерируем и на каждую итерацию выполняем...
Пожалуйста, обратите внимание, что пользователь заблокирован
отметил как "решение". Если что, это был не ТС, а я =)
А чем отличаются лайки и вот эти цифры под постом типа за/против?
 
Ок. Powershell. А он же .NET. Заюзаем новомодные фичи, не малварь же пишем под все ОС. Таргет WIN 10, думаю уже все обновились?))
Powershell 5+.

EnumerateFiles возвращает итератор. Таким образом можно осуществить lazy перебор файлов, не загружая список всех файлов в RAM. Просто лениво итерируем и на каждую итерацию выполняем разархивацию с помощью cmdleta Expand-Archive, не нужно ждать, пока загрузит весь список файлов в память.
Посмотреть вложение 16375
В то время, как GetFiles возвращает String[], который мы можем проитерировать ТОЛЬКО после получения всех элементов. (То, как сделано у остальных на батниках)
Посмотреть вложение 16376
Погнали.
Код:
function Extractor {
    param($from, $to, $archiveFormats)
    if($archiveFormats.Length -eq 0) {
        Write-Host 'You must specify archive formats'
        return
    }
    if($(Test-Path $to -PathType Container) -ne $True){
        New-Item $to -itemtype Directory
    }
    if($(Test-Path $from -PathType Container) -eq $True){
        foreach($iter in [System.IO.Directory]::EnumerateFiles($from)){
            Get-ItemProperty $iter | % {
                if($archiveFormats -contains $_.Extension) {
                    $dest = $to + '/' + $_.BaseName;
                    if($(Test-Path $dest)){
                        Remove-Item -Path $dest -Recurse
                    }
                    Expand-Archive -Path $_.FullName -DestinationPath $dest
                    Remove-Item -Path $_.FullName
                }
            }
        }
    }
    else {
        Write-Host "$from folder does not exists";
        return
    }
}

# Вызывать примерно так.
Extractor -from "...\extractorPS\archives" -to "...\extractorPS\result" -archiveFormats @('.zip', '.rar')
Аргументы:
-from "путь к папке с архивами"
-to "путь к папке, где будет разархивированный контент, если папки нет, она создается"
-archiveFormats расширения архивов, которые скрипт возьмет в работу.
Запускать powershell -ep bypass path_to_script.ps1
Потенциально можно улучшить:
1) Добавить потоки
2) Изменить логику проверки Extension файла, поскольку итератор возвращает только путь, но мы форсим создание обьекта FileInfo путем вызова Cmdleta Get-ItemProperty.
скинь btc в пм, решение хорошее
 
скинь btc в пм, решение хорошее
UPD. По фанчику решил запилить с потоками и выводом инфы. Интересно канеш, насколько увеличит по скорости. Если будет инфа по этому поводу, прошу отписать.
Код:
function ArchivesExtractor{
    param($threads, $from, $to, $archiveFormats)
    if($archiveFormats.Length -eq 0) {
        Write-Host '[-] You must specify archive formats'
        return
    }
    if($(Test-Path $to -PathType Container) -ne $True){
        New-Item $to -itemtype Directory
    }
    if($(Test-Path $from -PathType Container) -eq $True){

        # define worker scriptblock
        $worker = {
            param($iterator, $configuration) 
            Write-Host "[*] Processing $iterator `n"
            Get-ItemProperty $iterator | % {
                if($configuration.ArchiveFormats -contains $_.Extension) {
                    $dest = $configuration.To + '/' + $_.BaseName;
                    if($(Test-Path $dest)){
                        Remove-Item -Path $dest -Recursive
                    }
                    Expand-Archive -Path $_.FullName -DestinationPath $dest
                    Remove-Item -Path $_.FullName
                }
            }
            $configuration.Total += 1
            Write-Host "[+] Complete $iterator `n"
            Write-Host $("[+] Total: {0}  `n" -f $configuration.Total)
        }

        # create config hashtable for workers
        $configuration = [hashtable]::Synchronized(@{})
        $configuration.To = $to
        $configuration.ArchiveFormats = $archiveFormats
        $configuration.Total = 0

        # create runspace pool
        $sessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()
        $runspacePool = [RunspaceFactory]::CreateRunspacePool(1, $threads, $sessionState, $host)
        $runspacePool.Open()
        $Jobs = New-Object System.Collections.ArrayList

        # run workers
        foreach($iterator in [System.IO.Directory]::EnumerateFiles($from)){
            Write-Host "[+] Creating runspace for $iterator `n"
            $powerShell = [powershell]::Create()
            $powerShell.RunspacePool = $runspacePool
            $powerShell.AddScript($worker).AddArgument($iterator).AddArgument($configuration) | Out-Null
            while( $runspacePool.GetAvailableRunspaces() -lt 1 ) {
                Start-Sleep -Milliseconds 10
            }

            $JobObj = New-Object -TypeName PSObject -Property @{
                Runspace = $powerShell.BeginInvoke()
                PowerShell = $powerShell
            }

            $Jobs.Add($JobObj) | Out-Null 
                  
        }
        while ($Jobs.Runspace.IsCompleted -contains $false) {
            Write-Host (Get-Date).ToString() "Still running..."
            Start-Sleep 1
        }

    }
    else{
        Write-Host "[-] $from folder does not exists";
        return
    }
}

ArchivesExtractor -threads 2 -from "...\extractorPS\archives" -to "...\extractorPS\results" -archiveFormats @('.zip', '.rar')
 
Последнее редактирование:
А чем отличаются лайки и вот эти цифры под постом типа за/против?
Это в новом движке появилось, можно сделать что-то типо стековерфло, смысл такой, что пользователи отмечают посты, которые лучше всего подходят для решения какой-то проблемы, далее самый лучший пост можно либо пометить как решение, или он автоматически помечается как решение и всегда будет на видном месте в теме...

В целом кстати прикольно.)))

А репутация, это другое, лайки это просто благодарность автору, что-бы например каждый раз не захламлять тему "Спасибо", можно также недовольство выразить дизлайком...

Плюс лайки/дизлайки влияют на репутацию на форуме, там просмотр скрытого текста и т.д., а это просто рейтинг поста в теме и на репутацию никак не влияет.

Ну это так задумывалось из коробки в движке, так-то можно реализовать как угодно там, под конкретный сайт...
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх