【问题标题】:PowerShell script to combine CSVs and add root directory as an additional column用于组合 CSV 并将根目录添加为附加列的 PowerShell 脚本
【发布时间】:2022-01-13 20:36:23
【问题描述】:

我正在尝试编写我的第一个 PowerShell 脚本,但我正在努力理解面向对象和管道的方法。所以我有一个这样的目录结构(Google Takeout Nest 目录):

Path\DeviceID-A\
   - Year\
      - Month\
         - year-month-sensors-a.csv
Path\DeviceID-B\
   - Year\
      - Month\
         - year-month-sensors-b.csv
...

我想将所有 CSV 聚合在一起,我编写了一个简单的脚本来执行此操作:

Get-ChildItem -Recurse -Filter *.csv | Select-Object -ExpandProperty FullName | Import-Csv | Export-Csv merged.csv -NoTypeInformation -Append

但是,当所有内容聚合在一起时,我会丢失 DeviceID 的上下文。所以我想添加一个包含这些初始根目录的附加列,类似于:

Import-Csv merged.csv | Select-Object *,@{Name='nest_id';Expression={$nestDeviceID}} | Export-Csv merged-v2.csv -NoTypeInformation

因此,year-month-sensors-a.csv 中的每一行都会有一个名为 nest_id 的附加列,对于该根目录下的任何 CSV,其值为 DeviceID-A

...但是我不能完全协调这两个脚本如何以编程方式迭代它们,无论我需要使用ForEach-Object 还是管道。

任何建议将不胜感激!

【问题讨论】:

  • 结果将是 1 个合并的 CSV 与一个具有其父目录的新列,您非常接近,但是,我们可以假设所有 CSV 具有相同的标题吗?否则会导致错误。
  • 是的——抱歉,我应该说清楚的。幸好所有 CSV 格式完全相同。

标签: powershell csv get-childitem import-csv foreach-object


【解决方案1】:

在发布代码之前,我认为值得一提的是,只要所有 CSV 始终具有相同的标题/列,这应该可以工作。如果不是这种情况,可能会发生这样的事情:

@'
Col1,Col2
Val1,Val2
'@ |
ConvertFrom-Csv |
Export-Csv ./test.csv -NoTypeInformation

@'
Col1,NewCol
Val1,NewVal
'@ |
ConvertFrom-Csv |
Export-Csv ./test.csv -NoTypeInformation -Append

这样做会引发以下异常:

无法将 CSV 内容附加到以下文件:./test.csv。附加对象没有对应于以下列的属性:Col2。要继续使用不匹配的属性,请添加 -Force 参数,然后重试该命令。


要回答您的问题,您已经很接近了,但是,我认为这是不可能的,如果是的话,我当然不会推荐它(其他阅读您的代码的人会为此感谢您)。

我的意思是,在不使用循环(ForEach-Objectforeach)的情况下,将Get-ChildItem 转移到Import-Csv。这是您失去对 DeviceID 文件夹名称的引用的地方。

澄清要点:

  • 代码将首先将$mergedCsv 存储在内存中,在不需要时在每次循环迭代时将 (-Append) 附加到 Csv 将导致大量不必要的磁盘 I/O ,因此,效率不高。在这种情况下,这对您来说可能并不重要,但对您未来的脚本很有帮助。
  • $file.Directory.Parent.Parent.Name 应该给你DeviceID 文件夹名称,如果我错了,请更正。
  • 每次循环迭代都将导入每个 CSV 并附加新的 Nest_ID 列,其中包含 DeviceID 文件夹名称。
$mergedCsv = foreach($file in Get-ChildItem -Recurse -Filter *.csv)
{
    $nestDeviceID = $file.Directory.Parent.Parent.Name
    $csv = Import-Csv $file.FullName
    $csv | Select-Object *, @{
        Name = 'Nest_ID'
        Expression = { $nestDeviceID }
    }
}

# Inspect the Merged CSV
$mergedCsv | Out-GridView

# Export it
$mergedCsv | Export-Csv merged.csv -NoTypeInformation

【讨论】:

  • 谢谢圣地亚哥。它第一次完美运行——成功地将大约 100 个 CSV 合并到超过 210,000 行数据中!这也很有意义,我发现这更具可读性。 Out-GridView 也是一个简洁的功能。再次感谢!
  • @JamesM 乐于助人 :) 很高兴它在第一次尝试时奏效了呵呵
猜你喜欢
  • 2018-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多