【问题标题】:Export CSV. Folder, subfolder and file into separate column导出 CSV。文件夹、子文件夹和文件到单独的列
【发布时间】:2021-06-27 22:04:08
【问题描述】:

我创建了一个脚本,列出了所有文件夹、子文件夹和文件并将它们导出到 csv:

$path = "C:\tools"
Get-ChildItem $path -Recurse |select fullname | export-csv -Path "C:\temp\output.csv" -NoTypeInformation

但我希望 pfad 中的每个文件夹、子文件夹和文件都写入 csv 中的单独列。

类似这样的:

c:\tools\test\1.jpg

Column1 Column2 Column3
tools test 1.jpg

如果有任何帮助,我将不胜感激。

谢谢。

【问题讨论】:

  • 当你有 C:\tools\test\another\1.jpg 时会发生什么?其他人没有的全新专栏?与其他列之一结合?总的来说,最初,这听起来是个坏主意。
  • 子文件夹数量不变

标签: powershell csv export


【解决方案1】:

您可以使用Split() 方法拆分Fullname 属性。棘手的部分是您需要提前知道最大路径深度,因为 CSV 格式要求所有行具有相同数量的列(即使某些列是空的)。

# Process directory $path recursively
$allItems = Get-ChildItem $path -Recurse | ForEach-Object {

    # Split on directory separator (typically '\' for Windows and '/' for Unix-like OS)
    $FullNameSplit = $_.FullName.Split( [IO.Path]::DirectorySeparatorChar )  

    # Create an object that contains the splitted path and the path depth.
    # This is implicit output that PowerShell captures and adds to $allItems.
    [PSCustomObject] @{ 
        FullNameSplit = $FullNameSplit
        PathDepth     = $FullNameSplit.Count
    }
}

# Determine highest column index from maximum depth of all paths.
# Minus one, because we'll skip root path component.
$maxColumnIndex = ( $allItems | Measure-Object -Maximum PathDepth ).Maximum - 1

$allRows = foreach( $item in $allItems ) {

    # Create an ordered hashtable
    $row = [ordered]@{}

    # Add all path components to hashtable. Make sure all rows have same number of columns.
    foreach( $i in 1..$maxColumnIndex ) {
        $row[ "Column$i" ] = if( $i -lt $item.FullNameSplit.Count ) { $item.FullNameSplit[ $i ] } else { $null }
    }

    # Convert hashtable to object suitable for output to CSV.
    # This is implicit output that PowerShell captures and adds to $allRows.
    [PSCustomObject] $row
} 

# Finally output to CSV file
$allRows | Export-Csv -Path "C:\temp\output.csv" -NoTypeInformation

注意事项:

  • 语法Select-Object @{ Name= ..., Expression = ... } 创建一个calculated property
  • $allRows = foreach 捕获 foreach 循环的所有输出并将其分配给变量 $allRows,如果循环输出多个对象,它将是一个数组。这也适用于大多数其他控制语句,例如。 G。 ifswitch
  • 在循环中,我可以直接创建一个[PSCustomObject](并使用Add-Member 为其添加属性),而不是先创建一个哈希表,然后再转换为[PSCustomObject]。选择的方式应该更快,因为不需要调用 cmdlet 的额外开销。

【讨论】:

  • 谢谢!不幸的是,我在第 9 行收到错误:Measure-Object:在任何对象的输入中都找不到属性“$_.FullNameSplit.Count”
  • @EloBizne 该代码需要 PS7+,因为旧版 PS 不支持 Measure-Object 的计算属性。我也稍微更改了代码以支持 PS5。
  • 谢谢你,完美!我还必须使用恒定数量的 od 子文件夹执行第二个脚本(不需要测量对象)。在此脚本中,第一列的标题应为“项目”,并且始终具有相同的值“会计”。第二个应该是标题“1 Subfolder”,并将 1 Subfolder 名称作为值。 3 列应具有标题“文件”并作为值文件 namem,4 列应具有标题“创建日期”并将创建文件日期作为值。我绑定转换你的脚本来做到这一点,但我认为它不会工作。
  • @EloBizne 评论不应用于后续问题。如有必要,请创建一个新问题。
【解决方案2】:

虽然包含可变数量项目的行文件实际上不是 CSV 文件,但您可以自己滚动,Microsoft Excel 可以读取它。

=== Get-DirCsv.ps1

Get-Childitem -File |
    ForEach-Object {
        $NameParts = $_.FullName -split '\\'
        $QuotedParts = [System.Collections.ArrayList]::new()
        foreach ($NamePart in $NameParts) {
            $QuotedParts.Add('"' + $NamePart + '"') | Out-Null
        }
        Write-Output $($QuotedParts -join ',')
    }

使用它来捕获输出到一个文件:

.\Get-DirCsv.ps1 | Out-File -FilePath '.\dir.csv' -Encoding ascii

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多