簡體   English   中英

多個 csv 文件到一個 csv 文件 - Powershell

[英]Multiple csv files to one csv file - Powershell

我一直在閱讀有關該概念的一些以前的帖子,但是我發現所有解決方案彼此都非常不同。

我將多個 csv 划分到單獨的文件夾(所有路徑都相同,但子文件夾不同)。

我現在需要導入這些 csv,更改標題並將其導出為一個 csv。

我一直在嘗試這個,但我得到了一個非常奇怪的錯誤:Import-Csv:Cannot open file "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;

我正在考慮為標題使用數據表,但此時我還不太清楚。 錯誤的問題對我來說也不清楚......

正如已經指出的:

  • Import-Csv -Path $_應該是Import-Csv -Path $_.FullName在你的代碼中

    • (嚴格來說,應該是Import-Csv -LiteralPath $_.FullName ,因為傳遞給-Path參數的字符串需要進行通配符解析)。
  • 因為表示Get-ChildItem返回的文件[System.IO.FileInfo]實例在作為命令行參數(而不是通過管道)傳遞給-Path (或-LiteralPath )參數時被轉換為字符串,在這種情況下,如果您的Get-ChildItem命令以Windows PowerShell 中目錄為目標,則使用純文件名而不是完整路徑(請參閱下面的背景信息)。

    • 僅文件名(例如Book1.csv被解釋為相對於當前目錄(在您的情況下恰好是C:\\Windows\\system32 ),因此Import-Csv查找文件C:\\Windows\\system32\\Book1.csv而不是比預期的C:\\csv\\Book1.csv

    • 需要注意的是管道Get-ChildItem輸出的cmdlet一般不會受此影響,因為.PSPath包含完整路徑(包括PS提供商前綴)綁定到屬性(PowerShell中添加了幕后) -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] -to-string 轉換過程中出現問題。

如果[System.IO.FileInfo]實例一致評估為文件的完整路徑,也不會出現問題,不幸的是, Windows PowerShell 中並非如此(此問題已在 PowerShell Core 中修復):

  • Get-ChildItem <directory>輸出在字符串上下文中評估為文件名的[System.IO.FileInfo]實例。

  • Get-ChildItem <literalFilePathOrWildCardExpr>輸出評估為完整路徑的[System.IO.FileInfo]實例。

換句話說:只有當Get-ChildItem目錄(文件夾)為目標時,它返回的對象才僅在字符串上下文中評估其文件
相比之下,針對特定文件或使用通配符表達式會產生完整路徑; 使用Get-Item ,情況總是如此。

您只需要“全名”屬性,而不是“姓名”。

前任:

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

試試這個代碼。 此代碼獲取所有 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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM