【问题标题】:Multiple csv files to one csv file - Powershell多个 csv 文件到一个 csv 文件 - Powershell
【发布时间】:2017-06-07 06:24:19
【问题描述】:

我一直在阅读之前关于这个概念的一些帖子,但我发现的所有解决方案都彼此非常不同。

我有多个 csv 文件分布在单独的文件夹中(所有文件夹的路径相同,但子文件夹不同)。

我现在需要导入这些 csv,更改标题并将其导出到一个 csv 中。

我一直在尝试这样做,但我遇到了一个非常奇怪的错误:Import-Csv:无法打开文件“C:\Windows\system32\Book1.csv” 虽然我的路径是指 C:\csv ?

$CSVFolder = 'C:\csv\';                                                               #'
$OutputFile = 'C:\export\test3.csv';

$CSV= @();

Get-ChildItem -Path $CSVFolder -Filter *.csv | ForEach-Object { 
    $CSV += @(Import-Csv -Path $_)
}

$CSV | Export-Csv -Path $OutputFile -NoTypeInformation -Force;

我正在考虑为标题使用数据表,但目前对我来说还不是很清楚。我也不清楚错误的问题......

【问题讨论】:

  • 我猜使用$_.FullName
  • @(Import-Csv -Path $_.FullName)

标签: powershell csv merge


【解决方案1】:

如前所述:

  • Import-Csv -Path $_ 在你的代码中应该是Import-Csv -Path $_.FullName

    • (严格来说应该是Import-Csv -LiteralPath $_.FullName,因为传递给-Path参数的字符串要经过通配符解析)。
  • 因为代表Get-ChildItem返回的文件的[System.IO.FileInfo]实例在作为传递给-Path(或-LiteralPath)参数时被转换为字符串 >命令行参数(而不是通过管道),在这种情况下仅仅是文件名而不是完整路径如果您的Get-ChildItem 命令针对Windows PowerShell 中的目录,则使用em>(请参阅下面的背景信息)。

    • Book1.csv 这样的文件名被解释为相对于当前 目录(在您的情况下恰好是C:\Windows\system32),所以Import-Csv 查找文件@ 987654333@ 而不是预期的C:\csv\Book1.csv

    • 请注意,管道 Get-ChildItem 输出到 cmdlet 通常不会受此影响,因为 .PSPath 属性(PowerShell 在幕后添加)包含完整路径(包括 PS 提供程序前缀)绑定到 -LiteralPath 参数。
      但请注意,从 PSv5.1.14393.693 开始,由于一个错误,Import-Csv 的这种机制损坏


这是一个常见的陷阱,当[System.IO.FileInfo] 实例被传递给通过[string](-array) 类型的参数作为参数接受文件路径的cmdlet 时

为了安全起见:当您将从Get-ChildItem 接收到的对象传递给另一个命令时,请始终使用.FullName作为参数值(而不是通过管道)以确保完整路径通过。


可选背景信息:

这种行为是一个陷阱,因为假设将[System.IO.FileInfo] 实例按原样传递给接受文件路径的命令是完全合理的,给定PowerShell 面向对象的特性 - 特别是因为它确实在使用 管道 而不是参数值时可靠地工作。

不幸的是,接受文件路径(-Path-LiteralPath 参数)的内置 cmdlet 仅作为 [string]s 执行(没有直接接受 [System.IO.FileInfo] 实例的参数集),它是在[System.IO.FileInfo]转字符串的过程中出现问题。

如果[System.IO.FileInfo] 实例一致评估为文件的完整路径,也不会有问题,不幸的是,在Windows PowerShell(此问题已在 PowerShell Core 中得到修复):

  • Get-ChildItem <directory> 输出[System.IO.FileInfo] 实例,在字符串上下文中评估为文件名

  • Get-ChildItem <literalFilePathOrWildCardExpr> 输出评估为完整路径[System.IO.FileInfo] 实例。

换句话说:只有当Get-ChildItem目录(文件夹)为目标时,它返回的对象才会在字符串上下文中评估其文件名称
相比之下,针对特定文件或使用通配符表达式会产生完整路径; Get-Item 总是这样。

【讨论】:

    【解决方案2】:

    试试这个代码。此代码获取所有 csv 文件,导入它们并仅获取第 1、2、3 列并将列名更改为 header1、header2、header3,然后将全部导出到新的 csv 文件中

    Get-ChildItem "C:\temp2" -Filter "*.csv" | 
        %{Import-Csv $_.FullName -Header header1, header3,header4} | 
                        Export-Csv "c:\temp\result.csv" -NoTypeInformation
    
    
    #a short version (for no purist)
    gci "C:\temp2" -Filter "*.csv" | %{ipcsv $_.FullName -Header header1, header3,header4} | epcsv "c:\temp\result.csv" -NoType
    

    【讨论】:

      【解决方案3】:

      你只需要'fullname'属性,而不是'name'。

      例如:

      PS /Users/adil/Downloads> gi *csv |select name                                                                  
      
      Name              
      ----              
      tradesdownload.csv
      
      
      PS /Users/adil/Downloads> gi *csv |select name, fullname                                                                
      
      Name               FullName                                
      ----               --------                                
      tradesdownload.csv /Users/adil/Downloads/tradesdownload.csv
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-10-11
        • 1970-01-01
        • 2021-11-11
        • 1970-01-01
        • 2021-04-30
        • 2015-06-19
        • 1970-01-01
        • 2014-05-17
        相关资源
        最近更新 更多