Показать полную графическую версию : объединить данные из папок в один 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?
kontox, Вы ж не первый день на форуме — есть ряд вопросов, влияющих на код: какова кодировка файлов, есть ли BOM, если это юникод, какие концы строк, есть ли заголовки в файлах и т.д.
Упакуйте пару-тройку таких папок с файлами в один архив и выложите его на DropMeFiles.com.
Iska, есть системные умолчания, можно и нужно исходить из них. А прибивать к коду гвоздями чужеродные концы строк уже в случае необходимости.
1.csv (1kb)
2.csv(1kb)
3.csv(1kb)
4.csv(4kb)
5.csv(4kb)
6.csv(4kb)
7.csv(4kb) »
Ну и у какого файла тут максимальный размер?! По описанию складывается впечатление, что обобщающий файл будет по размеру как сумма остальных файлов (за вычетом заголовков).
везде все поля одинаковые.
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
}
везде все поля одинаковые. »
# Корневой каталог
$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
Однострочник:
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, это сквозной pipeline - результирующий файл создаётся когда ещё не все директории прочитаны
Busla, спасибо, ясно, такой фокус не сработает.
Iska, подскажите, я пытаюсь использовать ваше решение, но выходит ошибка.
скрин
kontox, похоже, у вас старая версия powershell
какая ОС?
по идее, этот код надо класть в файл с расширением ps1 и запускать как скрипт
Busla, windows 7 x32
я с расширением ps1 и делал.
Busla, проверил, Вы правы. Дело в версии PS. Код от Iska шикарно отработал.
Iska, Busla, а можно вас попросить усложнить код ps.
$sRootFolder = 'C:\Мои проекты\0203'
допусти проектов 10
$sRootFolder = 'C:\Мои проекты\0204'
$sRootFolder = 'C:\Мои проекты\0205'
$sRootFolder = 'C:\Мои проекты\0206'
...
Как сделать чтобы для всех этих папок создавались файлы csv(в каждой отдельно соответственно). Потому что Каждый проект отдельная аналитика
а то для каждый папки придется создать 10 ps файлов))
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
}
}
Iska, из-за своей невнимательность я оплошал и ещё как. Дело в том, что я думал, что все файлы, у который идет одинаковый размер , они содержат одинаковые данные
1.csv (1kb)
2.csv(1kb)
3.csv(1kb)
4.csv(4kb)
5.csv(4kb)
6.csv(4kb)
7.csv(4kb) »
На деле, после ручного анализа они имеют одинаковый размер, но данные разные там, не колонки, а именно их значения
Можно ли скрипт переделать, чтобы он просто все csv объединял в один. без учета размера.
То есть, все *.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
}
}
Можно ли скрипт переделать, чтобы он просто все 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
Друзья, подскажите, вот код
вот код
$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
}
}
как сделать, чтобы напротив строки, было указано из какой подпапки строка?
пример на снике
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.