使用Powershell从一个文件夹中删除多个CSV文件的前15行

3

我有一个 Powershell 脚本,可以很好地从单个 CSV 文件中删除前 15 行。

$import = get-content c:\temp\test.csv
$import | Select-Object -Skip 15 | Set-Content c:\temp\test2.csv

我希望您能够在一个文件夹中循环遍历多个CSV文件。但我不太清楚如何实现这一点。

我没有测试工具,但是从记忆中来看,这应该可以工作:Import-Csv -Path C:\temp\text.csv | Select-Object -Skip 15 | Export-Csv -Path C:\temp\test2.csv -NoTypeInformation - Persistent13
使用 Get-ChildItem 命令获取文件列表,然后通过管道传递到 ForEach-Object 中进行迭代,将您的代码放在“F-O”循环中。这似乎可以完成您的任务。 [微笑] - Lee_Dailey
2个回答

0

可选的-NumberOfLines参数,默认为15

可选的-Verbose参数将输出已修改的文件。

function Remove-CSVLines {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$FolderPath,

        [int]$NumberOfLines = 15
    )
    process{
        $fileList = (Get-ChildItem -Path $FolderPath -Filter '*.csv')

        foreach ($file in $fileList){
            $csvObject = Import-Csv -Path $file.PSPath
            $csvObject | Select-Object -Property * -Skip $NumberOfLines | Export-CSV -Path $file.PSPath -Force -NoTypeInformation
            Write-Verbose -Message "Removed $NumberOfLines lines from $file"
        }
    }
}

Remove-CSVLines -FolderPath .\myfolder

你已经很好地打包了功能,但说实话,我认为这种打包有点分散了解决方案的本质。事实证明(这个问题并不明显),OP真正想要的是从文件中删除前15行,这些行显然包含非CSV数据。你的解决方案适用于需要删除前15个数据行的正确CSV文件,但请注意,通过Import-CsvExport-Csv进行往返转换既费时又可能改变文件的引号和编码特性(关于后者,-Encoding是你的朋友)。 - mklement0
请注意,Select-Object -Property * 会不必要地创建输入对象的 _副本_;在这种情况下,并且为了重新导出到 CSV,这只是一种低效率,但请注意,对于非自定义对象作为输入,可能会丢失信息。简而言之:使用 Select-Object -Property * -Skip $NumberOfLines 跳过 $NumberOfLines 个对象,并将其余对象 原样 传递。 - mklement0
谢谢您的解释。您介意详细说明一下如何使用Select-Object可能会导致非自定义对象的丢失吗?我一直在努力提高我的知识水平。 - Bennett
使用Select-Object -Property ...创建了类型为[pscustomobject]的“属性包”对象,这些对象与输入对象的类型明显不同,并且具有输入对象属性的静态副本,并且缺少输入对象上存在的任何非属性成员,尤其是方法。 - mklement0

0
这是一种单管道解决方案,可将文件处理为文本文件,并跳过前15行数据,即保留标题行(CSV文件中的第一行,其中包含列名),并将每个*.csv文件的结果保存到相应的*2.csv文件中。
Get-ChildItem c:\temp -Filter *.csv | ForEach-Object {
  Get-Content $_.FullName | 
    Where-Object { $_.ReadCount -eq 1 -or $_.ReadCount -ge 17 } |  
      Set-Content ($_.FullName -replace '\.csv$', '2$&')
}

注意:要无条件删除前15行,请将Where-Object命令替换为:
Select-Object -Skip 15

请注意使用.ReadCount属性,该属性包含输入行号。 Get-Content会将此属性添加到从输入文件中读取的每一行。

使用Get-Content/Set-Content处理CSV文件作为文本文件(而不是使用Import-Csv/Export-Csv),可以实现更快的处理(并保留围绕值的双引号的存在/不存在),但是有一个关于假定“文本行”与“CSV行”相同的警告:虽然CSV行通常与文本文件行相同,但并非一定如此:如果使用"..."括起来的CSV列值可能跨越多行。
还要注意,在Windows PowerShell中,默认情况下Set-Content将创建"ANSI"编码输出文件,而与输入编码无关;在PowerShell Core中,您最终将得到没有BOM的UTF-8编码文件。使用-Encoding控制输出编码。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接