Подсчет строк в заархивированных файлах с помощью Windows PowerShell

Есть папка, которая содержит более 1000 заархивированных файлов. Каждый заархивированный файл содержит 12 других заархивированных файлов, каждый из которых содержит по одному файлу CSV. Мне нужно подсчитать общее количество строк всех файлов...

Это можно сделать с помощью Windows PowerShell, но у меня проблемы с тем, чтобы разархивировать файлы, подсчитать количество строк и снова заархивировать, чтобы сэкономить место на диске во время процесса.

$folderPath="C:\_Unzip_Folder";

Get-ChildItem $folderPath -recurse | %{ 

    if($_.Name -match "^*.`.zip$")
    {
        $parent="$(Split-Path $_.FullName -Parent)";    
        write-host "Extracting $($_.FullName) to $parent"

        $arguments=@("e", "`"$($_.FullName)`"", "-o`"$($parent)`"");
        $ex = start-process -FilePath "`"C:\Program Files\7-Zip\7z.exe`"" -ArgumentList $arguments -wait -PassThru;

        if( $ex.ExitCode -eq 0)
        {
            write-host "Extraction successful, deleting $($_.FullName)"
            rmdir -Path $_.FullName -Force
        }
    }
}

Get-ChildItem $folderPath -recurse -Filter *.csv | %{ 
    Get-Content $($_.FullName)  | Measure-Object -Line
}

cmd /c pause | out-null

Теперь он считает строки, но может быть проще, если он СУММУЛИРУЕТ их мне.

Кто-нибудь может помочь мне с этой задачей?

Спасибо вам всем.


person Gustavo_Oliveira    schedule 07.06.2020    source источник
comment
Попробуйте использовать цикл foreach, например foreach($file in $(gci C:\_Unzip_Folder)){if ($file.extension -eq ".csv"){foreach ($line in $(get-content $file.fullname)){$i++}}.   -  person Nico Nekoru    schedule 07.06.2020
comment
нет необходимости повторно архивировать файлы. вместо этого разархивируйте файлы во временный каталог, а затем, когда закончите с ними, удалите временные разархивированные файлы. возможно, просто удалите весь временный каталог для распаковки ... [ухмылка]   -  person Lee_Dailey    schedule 07.06.2020
comment
@NekoMusume Я не понял, что ты пытался мне объяснить...   -  person Gustavo_Oliveira    schedule 08.06.2020
comment
См. foreach -?   -  person Nico Nekoru    schedule 08.06.2020
comment
Просто добавьте Get-Content $($_.FullName) | Measure-Object –Line после инструкции Write-host "Extraction successful ..... Командлет Measure-Object подсчитывает количество строк в файле, если вы передаете ему параметр -Line.   -  person krokodilko    schedule 08.06.2020
comment
@krokodilkoЭто прекрасно работает, я изменил код выше, и возможно ли СУММИТЬ все количество строк и вернуть мне окончательное количество строк?   -  person Gustavo_Oliveira    schedule 08.06.2020
comment
Да, это возможно. Другой способ сделать это - сделать что-то вроде этого $(Get-Content $($_.FullName)).count, и результат будет таким же. Вы можете просмотреть файлы в папке и выполнить $var += $(Get-Content $($_.FullName)).count, чтобы добавить счетчики к переменной.   -  person Nico Nekoru    schedule 08.06.2020
comment
Полный: foreach($file in $(gci C:\_Unzip_Folder)){if ($file.extension -eq ".csv"){$var += $(Get-Content $($file.FullName)).count}}   -  person Nico Nekoru    schedule 08.06.2020


Ответы (1)


Вы также можете хранить все в памяти, например:

Set-StrictMode -Version "Latest"
$ErrorActionPreference = "Stop"
$InformationPreference = "Continue"

Add-Type -Assembly "System.IO.Compression.FileSystem"

$folderPath = "C:\_Unzip_Folder\*.zip"
$files      = Get-ChildItem $folderPath -Recurse
$csvCount   = 0
$lineCount  = 0
$bufferSize = 1MB
$buffer     = [byte[]]::new($bufferSize)

foreach ($file in $files)
{
    Write-Information "Getting information from '$($file.FullName)'"

    $zip  = [System.IO.Compression.ZipFile]::OpenRead($file.FullName)
    $csvs = $zip.Entries | Where-Object { [System.IO.Path]::GetExtension($_.Name) -eq ".csv" }
    foreach ($csv in $csvs)
    {
        $csvCount++
        Write-Information "Counting lines in '$($csv.FullName)'"

        $stream = $csv.Open()
        try
        {
            $byteCount = $stream.Read($buffer, 0, $bufferSize)
            while ($byteCount)
            {
                for ($i = 0; $i -lt $byteCount; $i++)
                {
                    # assume line feed (LF = 10) is the end-of-line marker
                    # you could also use carriage return (CR = 13)
                    if ($buffer[$i] -eq 10) { $lineCount++ }
                }
                $byteCount = $stream.Read($buffer, 0, $bufferSize)
            }
        }
        finally
        {
            $stream.Close()
        }
    }
}

Write-Information "Counted a total of $lineCount line(s) in $csvCount CSV-file(s)"
person mhu    schedule 08.06.2020