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为例):
| Name | Parent1 | Parent2 | Parent3 | Parent4 | Parent5 | Parent6 | Filename |
|---|---|---|---|---|---|---|---|
| file.txt | Folder1 | Folder2 | Folder3 | file.txt | |||
| image1.png | Folder1 | image1.png | |||||
| Doc1.docx | Folder1 | Folder2 | Folder3 | Folder4 | Folder5 | Folder6 | Doc1.docx |
| table3.csv | Folder1 | Folder2 | table3.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
关键修正点:
- 拆分目录路径而非完整路径:使用
$_.DirectoryName拆分,避免把文件名混入文件夹层级中。 - 计算相对层级:从目标目录
C:\Test之后的文件夹开始计数,确保Parent1对应目标目录下的第一级子文件夹。 - 固定最大层级列:直接按需求设置10级Parent列,不用动态计算最大值,符合用户最多10级的要求。
- 调整列顺序:按用户期望的顺序添加Name、Parent1~Parent10、Filename列,避免循环内重复赋值。
运行修正后的脚本,就能得到符合要求的CSV文件,不会出现最后一列显示文件名的问题。
内容的提问来源于stack exchange,提问作者Kei
相关产品推荐
相关产品推荐

