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

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

kontox 29-09-2018 17:39 2833517

объединить данные из папок в один csv
 
У меня много файлов csv, которые находятся в разных папках. пример

"C:\Users\Admin\Downloads\28-09-2018_17-39-27\data\23842735206960137\files in csv"
next

"C:\Users\Admin\Downloads\28-09-2018_17-39-27\data\23842735207380137\files in csv"

В каждой папке примерно 30-35 файлов

мне нужно объединить их в один csv

Также, в каждой папке, например

23842735206960137
23842735207380137

не обязательно работать со всеми 34 файлами. Чтобы объединиться в один набор данных из каждой папки, мне нужно взять только один файл, который занимает больше места. Чтобы быть более понятным в папке

23842735206960137
такие файлы

1.csv (1kb)
2.csv(1kb)
3.csv(1kb)
4.csv(4kb)
5.csv(4kb)
6.csv(4kb)
7.csv(4kb)
ВСЕГДА другие файлы имеют тот же размер и тот же контент, который имеет csv с максимальным размером.

Т.Е.

Итак, как только мы достигнем первого файла с максимальным размером, все остальные файлы имеют одинаковый размер и содержат одну и ту же информацию, что и самый первый с макс размером. Поэтому мы берем только первый файл с максимальным размером из каждой папки, а затем объединяем эти файлы в один набор данных.

Как это сделать в Powershell?

Iska 29-09-2018 19:04 2833526

kontox, Вы ж не первый день на форуме — есть ряд вопросов, влияющих на код: какова кодировка файлов, есть ли BOM, если это юникод, какие концы строк, есть ли заголовки в файлах и т.д.

Упакуйте пару-тройку таких папок с файлами в один архив и выложите его на DropMeFiles.com.

Busla 30-09-2018 12:03 2833626

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

Цитата:

Цитата kontox
1.csv (1kb)
2.csv(1kb)
3.csv(1kb)
4.csv(4kb)
5.csv(4kb)
6.csv(4kb)
7.csv(4kb) »

Ну и у какого файла тут максимальный размер?! По описанию складывается впечатление, что обобщающий файл будет по размеру как сумма остальных файлов (за вычетом заголовков).

kontox 30-09-2018 13:04 2833641

везде все поля одинаковые.

Iska 30-09-2018 14:54 2833657

kontox, попробуйте так:
Скрытый текст
Код:

$sRootFolder = 'C:\Мои проекты\0203'

if([System.IO.Directory]::Exists($sRootFolder)) {
    Get-ChildItem -Path $sRootFolder -Directory |`
        ForEach-Object -Process {
            Get-ChildItem -Path $_.FullName -File -Recurse -Include "*.csv" |`
                ForEach-Object -Begin {
                    $oFileInfo = $null
                } -Process {
                    if($_.Length -ge $oFileInfo.Length) {
                        $oFileInfo = $_
                    }
                } -End {
                    $oFileInfo
                }
        } | ForEach-Object -Begin {
            $aContent = @()
        } -Process {
            $aCurrContent = [System.IO.File]::ReadAllLines($_.FullName)

            if($aContent.Count -eq 0) {
                $aContent += $aCurrContent
            } else {
                $aContent += $aCurrContent[1..$($aCurrContent.Count - 1)]
            }
        } -End {
            [System.IO.File]::WriteAllText("$sRootFolder\$(([System.IO.DirectoryInfo]::new($sRootFolder).BaseName)).csv", [System.String]::Join("`n", $aContent))
        }
} else {
    Write-Host "Can't find root folder [$sRootFolder]." -ForegroundColor Red
}


YuS_2 30-09-2018 15:09 2833660

Цитата:

Цитата kontox
везде все поля одинаковые. »

Код:

# Корневой каталог
$fld = 'test'
# Фильтр файлов
$flt = '*.csv'
# Выходной файл .csv
$out = 'test.csv'

if (test-path $out){del $out}

dir $fld\* -dir|%{
        dir $_.fullname -filt $flt -file|sort -prop length -des|`
        select -first 1|%{import-csv $_.fullname -del ';'}
}|sort -prop date|export-csv $out -not -app


Busla 01-10-2018 12:15 2833771

Однострочник:
Код:

Get-ChildItem ./ -Recurse -File -Filter "*.csv" | Group-Object -Property PSParentPath | % { $max = @{ value = 0; object = $null }; $_.Group | % { if ($max.value -le $_.length) { $max.value=$_.value; $max.object=$_ }}; $max.object } | % {Import-Csv $_.FullName -Delimiter ';' } | Export-Csv -NoTypeInformation -Delimiter ';' ..\all.csv
Откуда начинать поиск - в первой команде, сейчас от текущей директории.
Куда складывать - путь к файлу в самом конце
(если итоговой файл попытаться положить внутри директорий для поиска - будет плохо)

Iska 01-10-2018 12:45 2833780

Цитата:

Цитата Busla
(если итоговой файл попытаться положить внутри директорий для поиска - будет плохо) »

А если перед началом поиска его тупо удалять?

Busla 01-10-2018 14:01 2833799

Iska, это сквозной pipeline - результирующий файл создаётся когда ещё не все директории прочитаны

Iska 01-10-2018 17:10 2833828

Busla, спасибо, ясно, такой фокус не сработает.

kontox 02-10-2018 14:45 2833983

Вложений: 1
Iska, подскажите, я пытаюсь использовать ваше решение, но выходит ошибка.
скрин

Busla 02-10-2018 15:40 2833988

kontox, похоже, у вас старая версия powershell
какая ОС?

по идее, этот код надо класть в файл с расширением ps1 и запускать как скрипт

kontox 02-10-2018 15:48 2833991

Busla, windows 7 x32

я с расширением ps1 и делал.

Busla, проверил, Вы правы. Дело в версии PS. Код от Iska шикарно отработал.

kontox 04-10-2018 13:46 2834377

Iska, Busla, а можно вас попросить усложнить код ps.
$sRootFolder = 'C:\Мои проекты\0203'
допусти проектов 10
$sRootFolder = 'C:\Мои проекты\0204'
$sRootFolder = 'C:\Мои проекты\0205'
$sRootFolder = 'C:\Мои проекты\0206'
...
Как сделать чтобы для всех этих папок создавались файлы csv(в каждой отдельно соответственно). Потому что Каждый проект отдельная аналитика
а то для каждый папки придется создать 10 ps файлов))

Iska 04-10-2018 22:24 2834468

kontox, не надо создавать 10 файлов проектов. Можно задать получение «корневого» каталога параметром скрипта и десять раз вызвать его из пакетного файла, передав одному и тому же скрипту, соответственно, десять разных аргументов. Можно просто оформить текущее содержимое отдельной функцией, где параметром функции будет «корневой» каталог и вызывать её десять раз, передавая ей каждый раз другой аргумент.

Или тупо, по рабоче-крестьянски, просто перечислить, або массивом, в том же самом коде, например:
Скрытый текст
Код:

$aRootFolders = @('C:\Мои проекты\0203', 'C:\MyProjects\0002', 'C:\Мои проекты\0206', 'C:\Мои проекты\0207', 'C:\MyProjects\0003')

foreach($sRootFolder in $aRootFolders) {
    if([System.IO.Directory]::Exists($sRootFolder)) {
        Write-Host "[$sRootFolder]" -ForegroundColor Green

        Get-ChildItem -Path $sRootFolder -Directory -Depth 1 |`
            ForEach-Object -Process {
                Write-Host "    [$($_.Name)]" -ForegroundColor Green

                Get-ChildItem -Path $_.FullName -File -Recurse -Include "*.csv" |`
                    ForEach-Object -Begin {
                        $oFileInfo = $null
                    } -Process {
                        if($_.Length -ge $oFileInfo.Length) {
                            $oFileInfo = $_
                        }
                    } -End {
                        Write-Host "        $($oFileInfo.Name)" -ForegroundColor Cyan
                        $oFileInfo
                    }
            } | ForEach-Object -Begin {
                $aContent = @()
            } -Process {
                $aCurrContent = [System.IO.File]::ReadAllLines($_.FullName)

                if($aContent.Count -eq 0) {
                    $aContent += $aCurrContent
                } else {
                    $aContent += $aCurrContent[1..$($aCurrContent.Count - 1)]
                }
            } -End {
                $sResultFileName = "$sRootFolder\$(([System.IO.DirectoryInfo]::new($sRootFolder).BaseName)).csv"
                Write-Host "$sResultFileName`r`n" -ForegroundColor Yellow
                [System.IO.File]::WriteAllText($sResultFileName, [System.String]::Join("`n", $aContent))
            }
    } else {
        Write-Host "Can't find root folder [$sRootFolder]." -ForegroundColor Red
    }
}


kontox 07-10-2018 15:31 2834855

Iska, из-за своей невнимательность я оплошал и ещё как. Дело в том, что я думал, что все файлы, у который идет одинаковый размер , они содержат одинаковые данные

1.csv (1kb)
2.csv(1kb)
3.csv(1kb)
4.csv(4kb)
5.csv(4kb)
6.csv(4kb)
7.csv(4kb) »

На деле, после ручного анализа они имеют одинаковый размер, но данные разные там, не колонки, а именно их значения

Можно ли скрипт переделать, чтобы он просто все csv объединял в один. без учета размера.

Iska 07-10-2018 16:29 2834859

То есть, все *.csv из всех подкаталогов первого уровня очередного «корневого» каталога объединяются в один, я правильно понимаю?

Попробуйте так:
Скрытый текст
Код:

$aRootFolders = @('C:\Мои проекты\0203', 'C:\MyProjects\0002', 'C:\Мои проекты\0206', 'C:\Мои проекты\0207', 'C:\MyProjects\0003')

foreach($sRootFolder in $aRootFolders) {
    if([System.IO.Directory]::Exists($sRootFolder)) {
        Write-Host "[$sRootFolder]" -ForegroundColor Yellow

        $aContent = @()

        Get-ChildItem -Path $sRootFolder -Directory -Depth 1 |`
            ForEach-Object -Process {
                Write-Host "  [$($_.Name)]" -ForegroundColor Green

                Get-ChildItem -Path "$($_.FullName)\*.*" -File -Include "*.csv" |`
                    ForEach-Object -Process {
                        Write-Host "    --> $($_.Name)" -ForegroundColor Cyan

                        $aCurrContent = [System.IO.File]::ReadAllLines($_.FullName)

                        if($aContent.Count -eq 0) {
                            $aContent += $aCurrContent
                        } else {
                            $aContent += $aCurrContent[1..$($aCurrContent.Count - 1)]
                        }
                    }
            }
        $sResultFileName = "$sRootFolder\$(([System.IO.DirectoryInfo]::new($sRootFolder).BaseName)).csv"
        Write-Host "<-- $sResultFileName`r`n" -ForegroundColor Magenta
        [System.IO.File]::WriteAllText($sResultFileName, [System.String]::Join("`n", $aContent))#>
    } else {
        Write-Host "Can't find root folder [$sRootFolder]." -ForegroundColor Red
    }
}


YuS_2 07-10-2018 19:46 2834884

Цитата:

Цитата kontox
Можно ли скрипт переделать, чтобы он просто все csv объединял в один. без учета размера. »

Код:

# Корневой каталог
$fld = 'test'
# Фильтр файлов
$flt = '*.csv'
# Выходной файл .csv
$out = 'test.csv'

dir $fld\* -dir|%{dir $_.fullname -filt $flt -file}|%{import-csv $_.fullname -del ';'}|sort -prop date|export-csv $out -not


kontox 25-10-2018 15:24 2837565

Вложений: 1
Друзья, подскажите, вот код
вот код


$aRootFolders = @('C:\Intel\Game_4', 'C:\Intel\Game_5')

foreach($sRootFolder in $aRootFolders) {
if([System.IO.Directory]::Exists($sRootFolder)) {
Write-Host "[$sRootFolder]" -ForegroundColor Yellow

$aContent = @()

Get-ChildItem -Path $sRootFolder -Directory -Depth 1 |`
ForEach-Object -Process {
Write-Host " [$($_.Name)]" -ForegroundColor Green

Get-ChildItem -Path "$($_.FullName)\*.*" -File -Include "*.csv" |`
ForEach-Object -Process {
Write-Host " --> $($_.Name)" -ForegroundColor Cyan

$aCurrContent = [System.IO.File]::ReadAllLines($_.FullName)

if($aContent.Count -eq 0) {
$aContent += $aCurrContent
} else {
$aContent += $aCurrContent[1..$($aCurrContent.Count - 1)]
}
}
}
$sResultFileName = "$sRootFolder\$(([System.IO.DirectoryInfo]::new($sRootFolder).BaseName)).csv"
Write-Host "<-- $sResultFileName`r`n" -ForegroundColor Magenta
[System.IO.File]::WriteAllText($sResultFileName, [System.String]::Join("`n", $aContent))#>
} else {
Write-Host "Can't find root folder [$sRootFolder]." -ForegroundColor Red
}
}

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


пример на снике


Время: 23:11.

Время: 23:11.
© OSzone.net 2001-