我有一个Powershell脚本,可以从单个CSV文件中整齐地删除前15行。
$import = get-content c:\temp\test.csv
$import | Select-Object -Skip 15 | Set-Content c:\temp\test2.csv
我想通过一个文件夹中的多个CSV文件循环它。无法弄清楚如何做到这一点。
这是一个单管道解决方案,它将文件作为文本文件处理并跳过前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
将此属性添加到它从输入文件中读取的每一行。
将CSV文件作为文本文件处理(使用Get-Content
/ Set-Content
而不是使用Import-Csv
/ Export-Csv
)可以加快处理速度(并保留双引号的存在/不存在),但需要注意的是,文本行是与CSV行相同:虽然CSV行通常与文本文件行相同,但不一定如此:如果"..."
包含,则CSV列值可能跨越多行。
另请注意,在Windows PowerShell中,Set-Content
默认会创建“ANSI”编码的输出文件,与输入编码无关;在PowerShell Core中,您最终将获得无BOM的UTF-8编码文件。使用-Encoding
来控制输出编码。
可选的-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