【问题标题】:Using a ForEach loop to reverse csv files使用 ForEach 循环反转 csv 文件
【发布时间】:2017-04-06 19:26:56
【问题描述】:

我需要做的是获取一些文本文件(csv,都在一个目录中)并创建文件,其中整个输出逐行反转,但将标题保持在顶部而不是在底部。

我可以获取一个文件(按名称)并复制第一行并创建一个仅包含该行的新文件。然后我将原始文件减去第一行,将其读入一个数组并反转它。然后我将它附加到只有标题的文件中。它工作正常,除了输出名称,我想是[file-REV.csv],但到目前为止我只得到[file.csv-REV]...

所以,一旦我完成了这项工作,我认为是时候让程序在目录中找到所有 csv 并循环遍历它们,为每个文件创建一个反向文件。

这是我目前所拥有的:

cd c:\users\$([Environment]::UserName)\working

$Path = "c:\users\$([Environment]::UserName)\working\"

ForEach ($file in Get-ChildItem -Filter *.csv) {
    Get-Content $file  -totalcount 1 | Set-Content .\$file-REV.csv
    $flip = (get-content | select -Skip 1)
    [array]::Reverse($flip)
    $flip | add-content "$file-REV.csv"
 }

这是我在执行脚本时收到的消息:

cmdlet Get-Content 在命令管道位置 1

为以下参数提供值:

路径[0]:

我尝试输入整个路径Get-Content -Path c:\users\jmurphy\working\,然后它抱怨找不到整个路径。

【问题讨论】:

  • 我建议的第一件事是查看Get-Help Get-ChildItem -DetailedGet-Help Get-Content -Detailed 的输出。您会发现Get-Help cmdlet 是学习如何使用 PowerShell 时最有用的命令之一。
  • 忽略潜在的其他问题给Get-Content 来自您创建的循环$flip = (get-content $file | select -Skip 1) 的文件名。 c:\users\jmurphy\working 是文件夹.. 不是文件。
  • 谢谢你们。我将从你的建议开始。我什至不知道 Get-Help(MS-man 就是它的名字)。谢谢!

标签: powershell csv foreach


【解决方案1】:

几件事。首先,您要定义要在变量中工作的文件夹,因此请在 Get-ChildItem 中使用它。 (出于习惯,我将名称更改为 $Folder,因为 $Path 已在 Environment 范围内使用变量。此外,$env: 是从 Environment 范围内读取变量的更快方法。)。

$Folder = "C:\Users\$env:UserName\working\"
$Files = Get-ChildItem $Folder -Filter *.csv

其次,您只想使用 Get-ChildItem 返回的内容中的 Fullname 属性,因为这是每个文件的完整路径。

ForEach ($File in $Files) {

因此,您需要在 Get-Content 中使用该文件的完整路径

Get-Content $File.Fullname -totalcount 1 | Set-Content .\$($file.Basename)-REV.csv

当您再次调用Get-Content 时,您将希望再次使用$File 作为文件的路径:

$Flip = (Get-Content $File.Fullname | Select -Skip 1)

Basename 是来自Get-Childitem 的属性,只有文件名,没有扩展名。您可以通过括在$() 中来强制评估双引号内变量的属性。

$Flip | Add-Content "$($file.Basename)-REV.csv"

整个脚本应该如下所示:

$Folder = "C:\Users\$env:UserName\working\"
$Files = Get-ChildItem $Folder -Filter *.csv
ForEach ($File in $Files) {
    Get-Content $File.Fullname -totalcount 1 | Set-Content .\$($file.Basename)-REV.csv
    $Flip = (Get-Content $File.Fullname | select -Skip 1)
    [array]::Reverse($Flip)
    $Flip | Add-Content "$($file.basename)-REV.csv"
}

【讨论】:

  • 嘿,本,很好的答案!您应该删除路径中的尾部斜杠,以便 StackOverflow 语法突出显示正常工作,而不是将整个代码块解释为字符串。 (反斜杠字符在 C# 等其他语言中是转义字符)
  • @Bluecakes 真的不需要。看看编辑。发生这种情况时,我使用<!-- language-all: lang-cs --> 以免过多地更改源。它并不完美,但更好一点
  • 虽然它的成本不是很高,但为什么不只读取一次文件并相应地拆分。此外,我认为您不需要专门使用 fullname 属性只需 $file 即可。
  • 本,非常感谢您的故障。当我运行它时,它“有点”工作。我得到了所有反向文件,但是每个文件运行都有一个错误,并且文件没有标题。这是错误:
  • >
【解决方案2】:

Joe,您在学习 PowerShell 方面做得很好。您只需要更多地利用面向对象的力量。

您已经知道 Get-ChildItem 将返回有关文件的对象。您需要知道的是该对象中包含的成员。使用 Get-Member 找出答案。

$file = Get-ChildItem .\t.csv
$file | Get-Member

一旦你找到一个有趣的成员,看看它的价值是什么。

$file.Name
$file.Extension
$file.BaseName

由此,您可以构造一个新的文件名。

$newFilename = $file.Basename + '-REV' + $file.Extension

把它放在 Get-Content 行之前。然后将 $newFilename 与 Add-Content 一起使用。

【讨论】:

    猜你喜欢
    • 2019-10-23
    • 2018-11-07
    • 1970-01-01
    • 1970-01-01
    • 2021-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多