PS 脚本正在导出空 CSV

PS Script is exporting an empty CSVs

我费了好大的劲才弄明白为什么这个脚本没有按预期工作。这是一个简单的脚本,我试图在其中导入 CSV,select 我想要的几列,然后导出 CSV 并复制自身。 (基本上我们已经归档了数据,由于内存大小限制,我只需要从另一个项目中提取几列)。这个脚本非常简单,它显然与它在不起作用时造成的挫败感成反比关系……现在的最终结果是我得到一个空的 csv,而不是只包含列的 csv selected with Select-Object.

$RootPath = "D:\SomeFolder"

$csvFilePaths = Get-ChildItem $RootPath -Recurse -Include *.csv | 
    ForEach-Object{
        Import-CSV $_ |
        Select-Object Test_Name, Test_DataName, Device_Model, Device_FW, Data_Avg_ms, Data_StdDev | 
        Export-Csv $_.FullName -NoType -Force
}

正如 Matt 评论的那样,您的最后一个 $PSItem ($_) 不再与 Get-ChildItem 相关,而是与没有 FullName [=23= 的 Select-Object cmdlet 相关]

您可以使用不同的 foreach 方法:

$RootPath = "D:\SomeFolder"
$csvFilePaths = Get-ChildItem $RootPath -Recurse -Include *.csv

foreach ($csv in $csvFilePaths)
{
Import-CSV $csv.FullName |
Select-Object Test_Name,Test_DataName,Device_Model,Device_FW,Data_Avg_ms,Data_StdDev | 
Export-Csv $csv.FullName -NoType -Force
}

或者保留您的代码,添加 $CsvPath 包含 csv 路径的变量,稍后使用它:

$RootPath = "D:\SomeFolder"
Get-ChildItem $RootPath -Recurse -Include *.csv | ForEach-Object{
$CsvPath = $_.FullName
Import-CSV $CsvPath |
Select-Object Test_Name,Test_DataName,Device_Model,Device_FW,Data_Avg_ms,Data_StdDev | 
Export-Csv $CsvPath -NoType -Force
}

除非您预先完整地将输入文件读入内存,否则您无法在给定管道中安全地读取和写回同一文件.

具体来说,Import-Csv file.csv | ... | Export-Csv file.csv这样的命令会擦除file.csv的内容。

最简单的解决方案是将读取输入文件的命令附在(...)中,但要注意:

  • 文件的内容(转化为objects)必须整体装入内存 .

  • 如果管道在所有(已转换的)object 被写回到文件.

应用于您的命令:

$RootPath = "D:\SomeFolder"

Get-ChildItem $RootPath -Recurse -Include *.csv -OutVariable csvFiles | 
    ForEach-Object{
        (Import-CSV $_.FullName) | # NOTE THE (...)
          Select-Object Test_Name, Test_DataName, Device_Model, Device_FW, 
                        Data_Avg_ms, Data_StdDev | 
            Export-Csv $_.FullName -NoType -Force
}

请注意,我使用 -OutVariable csvFiles 来收集输出变量 $csvFiles 中的 CSV file-info objects。您尝试通过 $csvFilePaths = ... 收集文件路径的尝试不起作用,因为它试图收集 Export-Csv 输出,但 Export-Csv 没有产生输出。

此外,为了安全起见,我已将 Import-Csv 参数从 $_ 更改为 $_.FullName 以确保 Import-Csv 找到输入文件(因为,很遗憾, file-info object $_ 绑定为 字符串有时 扩展为 仅仅是文件名).


一个更安全的解决方案是先输出到一个临时文件,并且(仅)在成功完成后替换原始文件。

无论采用哪种方法,替换文件都将具有默认文件属性和权限;如果原始文件具有您要保留的特殊属性 and/or 权限,则必须明确地重新创建它们。

所以我想通了。我试图直接通过 Import-Csv cmdlet 进行管道传输,而不是将其声明为 o.g 中的变量。代码。这是实现我想要完成的任务的代码片段。我之前试图直接在 Import-Csv cmdlet 中进行管道传输,我只需要声明一个使用 Import-Csv cmdlet 作为其定义的变量,并将该变量通过管道传输到 Select-Object,然后是 Export-Csv cmdlet。谢谢大家的帮助,我很感激!

$RootPath = "\someDirectory\"
$CsvFilePaths = @(Get-ChildItem $RootPath -Recurse -Include *.csv)
$ColumnsWanted = @('Test_Name','Test_DataName','Device_Model','Device_FW','Data_Avg_ms','Data_StdDev')
for($i=0;$i -lt $CsvFilePaths.Length; $i++){
  $csvPath = $CsvFilePaths[$i]
  Write-Host $csvPath
  $importedCsv = Import-CSV $csvPath 
  $importedCsv | Select-Object $ColumnsWanted | Export-CSV $csvPath -NoTypeInformation
}