将目录中的多个文件合并为一个文件

问题描述

我的目录树视图如下:

enter image description here

我想将目录中的多个文件合并(或假定附加)为单个文件。含义是文件夹中包含合并内容的单个文件。因此,每个文件夹将包含具有合并数据的单个文件。我尝试了以下方法,但是这种方法的问题在于它只能在一次迭代中读取单个文件

                string caminho = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
                string caminho_arquivo = Path.Combine(caminho,nome_arquivo);
                var decoded = Encoding.UTF8.GetString(Convert.FromBase64String(arquivo.arquivo));
                File.WriteallText(caminho_arquivo,decoded);

本质上,我希望一次迭代读取文件夹中的所有文件。然后将另一个文件夹中的数据放入下一个迭代中。在Powershell中推荐这样做的方法是什么?

解决方法

本质上,您的需求中有两个循环执行不同的事情,因此最好将它们作为代码中的不同循环来实现,而不是尝试通过单个递归循环来解决这两个任务。

究竟如何将JSON文件组合在一起取决于JSON文件包含的内容以及组合数据结构的意义。为简单起见,我将假设每个文件都包含一个字符串数组的JSON文件,而合并的版本只是每个数组的所有字符串的数组串联。

$Source = "C:\Path\To\Data"

foreach ($Directory in (Get-ChildItem $Source)) {

    $Result = @()

    foreach ($File in (Get-ChildItem $Directory\*.json)) {
        $Result += Get-Content $File | ConvertFrom-Json
    }

    $Result | ConvertTo-Json | Set-Content $Directory/Combined.json
}

在您的示例中,您只有一个目录级别,然后每个目录仅包含JSON文件,因此示例脚本对此进行了反映。如果脚本中的任何一个都是多级的,那么修改脚本都不会很困难。

,

最简单的方法是使用内部cmdlet

$dir = 'C:\Users\Alex\Desktop\In'
$items = get-childitem  $dir -recurse -filter '*.json'

$fileOut = Join-Path $dir -ChildPath 'out.txt'

$result = @()

foreach ($item in $items) {

     $result += (Get-Content $item.FullName | ConvertFrom-Json)
    

}
$result | ConvertTo-Json | out-file $fileOut

根据您的要求和您应使用的文件:

  • 对于非常大(>> 1.000)结果数组的数组列表,而不是Powershell数组
  • 用于获取非常大的单个文件(例如.net方法)的get-content解析器。

但是,只要这样做,就无需更改任何内容。

,

我认为这应该工作(未经测试)

[System.IO.Directory]::EnumerateDirectories('S:\SCRIPTS','*',[System.IO.SearchOption]::AllDirectories) | 
    ForEach-Object {
        [System.IO.File]::WriteAllText([System.IO.Path]::Combine($_,'Output.Json.combo'),# using .combo to avoind merging this output file next run
            ( @([System.IO.Directory]::EnumerateFiles($_) | 
            Where-Object { [System.IO.Path]::GetFileName($_) -like '*.json' } |
            ForEach-Object { [System.IO.File]::ReadAllText($_,[System.Text.Encoding]::UTF8) } |
            ForEach-Object { ConvertFrom-Json -InputObject $_  } ) |
            ConvertTo-Json -Depth 20 ),[System.Text.Encoding]::UTF8)
     }