You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell导出CSV:多级文件夹拆分为列并修正文件名列问题

问题:拆分文件路径为多级文件夹列+文件名列输出CSV

我有一个最多包含10级子文件夹的文件目录结构,需要通过PowerShell生成CSV文件,要求每个文件占一行,每个层级的文件夹作为单独的列,文件名单独放在一列中。

最初使用的命令:

gci -path C:\test -file -recurse|export-csv C:\temp\out.csv -notypeinformation

但这个命令导出的CSV中,目录是完整的长字符串,无法满足拆分层级的需求。

期望的输出格式(以C:\Test\Folder1\Folder2\Folder3\file.txt为例):

NameParent1Parent2Parent3Parent4Parent5Parent6Filename
file.txtFolder1Folder2Folder3file.txt
image1.pngFolder1image1.png
Doc1.docxFolder1Folder2Folder3Folder4Folder5Folder6Doc1.docx
table3.csvFolder1Folder2table3.csv

部分文件仅存于一级文件夹,部分存于多级文件夹,需保持格式统一,方便后续通过Power Automate和文件系统连接器读取表格路径,解析后在SharePoint中创建文件,并将文件夹层级作为元数据列。

我参考相关代码修改后,实现了文件名单独列,但脚本会在最后一列也添加文件名,需要解决这个问题。修改后的代码如下:

$allItems = Get-ChildItem C:\Test -File -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
        Filename = $_.Name
    }

}

# 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[ "Filename" ] = $item.Filename
        $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
} 

解决方案

问题根源在于原代码拆分的是文件完整路径(包含文件名),导致最后一个拆分元素是文件名,被当成了一个文件夹列;同时循环内重复赋值Filename列,逻辑混乱。

修正后的代码如下:

# 目标目录路径
$targetPath = "C:\Test"
# 最大文件夹层级(根据需求设置为10)
$maxFolderLevels = 10

$allItems = Get-ChildItem $targetPath -File -Recurse | ForEach-Object {
    # 拆分文件的目录路径(不包含文件名)
    $dirPathSplit = $_.DirectoryName.Split([IO.Path]::DirectorySeparatorChar)
    # 计算相对于目标目录的层级:从目标目录之后的部分开始算
    $relativeDirParts = $dirPathSplit | Select-Object -Skip ($dirPathSplit.IndexOf((Get-Item $targetPath).Name) + 1)

    [PSCustomObject]@{
        RelativeDirParts = $relativeDirParts
        Filename         = $_.Name
    }
}

$allRows = foreach($item in $allItems) {
    $row = [ordered]@{
        # 先添加Name列(和Filename列内容一致,按用户需求保留)
        "Name" = $item.Filename
    }

    # 添加Parent1到Parent10列
    for($i = 0; $i -lt $maxFolderLevels; $i++) {
        $columnName = "Parent$($i + 1)"
        $row[$columnName] = if($i -lt $item.RelativeDirParts.Count) { $item.RelativeDirParts[$i] } else { $null }
    }

    # 添加Filename列
    $row["Filename"] = $item.Filename

    [PSCustomObject]$row
}

# 导出到CSV
$allRows | Export-Csv -Path "C:\temp\out.csv" -NoTypeInformation -Encoding UTF8

关键修正点:

  1. 拆分目录路径而非完整路径:使用$_.DirectoryName拆分,避免把文件名混入文件夹层级中。
  2. 计算相对层级:从目标目录C:\Test之后的文件夹开始计数,确保Parent1对应目标目录下的第一级子文件夹。
  3. 固定最大层级列:直接按需求设置10级Parent列,不用动态计算最大值,符合用户最多10级的要求。
  4. 调整列顺序:按用户期望的顺序添加Name、Parent1~Parent10、Filename列,避免循环内重复赋值。

运行修正后的脚本,就能得到符合要求的CSV文件,不会出现最后一列显示文件名的问题。


内容的提问来源于stack exchange,提问作者Kei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 18:30:59