我有一个 Powershell 脚本,可以很好地从单个 CSV 文件中删除前 15 行。
$import = get-content c:\temp\test.csv
$import | Select-Object -Skip 15 | Set-Content c:\temp\test2.csv
我希望您能够在一个文件夹中循环遍历多个CSV文件。但我不太清楚如何实现这一点。
我有一个 Powershell 脚本,可以很好地从单个 CSV 文件中删除前 15 行。
$import = get-content c:\temp\test.csv
$import | Select-Object -Skip 15 | Set-Content c:\temp\test2.csv
可选的-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
Import-Csv
和Export-Csv
进行往返转换既费时又可能改变文件的引号和编码特性(关于后者,-Encoding
是你的朋友)。 - mklement0Select-Object -Property *
会不必要地创建输入对象的 _副本_;在这种情况下,并且为了重新导出到 CSV,这只是一种低效率,但请注意,对于非自定义对象作为输入,可能会丢失信息。简而言之:使用 Select-Object -Property * -Skip $NumberOfLines
跳过 $NumberOfLines
个对象,并将其余对象 原样 传递。 - mklement0Select-Object -Property ...
创建了类型为[pscustomobject]
的“属性包”对象,这些对象与输入对象的类型明显不同,并且具有输入对象属性的静态副本,并且缺少输入对象上存在的任何非属性成员,尤其是方法。 - mklement0Get-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列值可能跨越多行。Set-Content
将创建"ANSI"编码输出文件,而与输入编码无关;在PowerShell Core中,您最终将得到没有BOM的UTF-8编码文件。使用-Encoding
控制输出编码。
Import-Csv -Path C:\temp\text.csv | Select-Object -Skip 15 | Export-Csv -Path C:\temp\test2.csv -NoTypeInformation
- Persistent13Get-ChildItem
命令获取文件列表,然后通过管道传递到ForEach-Object
中进行迭代,将您的代码放在“F-O”循环中。这似乎可以完成您的任务。 [微笑] - Lee_Dailey