在Powershell traverse子文件夹中合并CSV文件-存档&;删除旧文件使用目标CSV的文件夹名称
我想将许多CSV文件合并成一个(几百个文件),删除添加的CSV的标题行 由于文件位于多个子文件夹中,我需要从根开始遍历所有子文件夹并处理其中的所有CSV。在合并之前,我想用zip对它们进行归档,删除旧的CSV。新合并的CSV文件和zip归档文件的名称应与其父文件夹相同 如果为同一文件夹再次启动脚本,则不应意外损坏或删除任何已处理的文件 我不是一个Powershell的家伙,所以我一直在从网上的几个资源中复制粘贴,并提出了以下解决方案(抱歉,不记得这些资源,如果您知道的话,可以在评论中随意添加引用) 这个补丁工作代码可以完成这项工作,但感觉不是很可靠。目前,它只处理子文件夹中的CSV文件。在给定的在Powershell traverse子文件夹中合并CSV文件-存档&;删除旧文件使用目标CSV的文件夹名称,powershell,csv,Powershell,Csv,我想将许多CSV文件合并成一个(几百个文件),删除添加的CSV的标题行 由于文件位于多个子文件夹中,我需要从根开始遍历所有子文件夹并处理其中的所有CSV。在合并之前,我想用zip对它们进行归档,删除旧的CSV。新合并的CSV文件和zip归档文件的名称应与其父文件夹相同 如果为同一文件夹再次启动脚本,则不应意外损坏或删除任何已处理的文件 我不是一个Powershell的家伙,所以我一直在从网上的几个资源中复制粘贴,并提出了以下解决方案(抱歉,不记得这些资源,如果您知道的话,可以在评论中随意添加引用
$targDir
中处理文件也很好
我想知道它是否可以更紧凑一些。欢迎提出改进建议
$targDir = "\\Servername\folder\"; #path
Get-ChildItem "$targDir" -Recurse -Directory |
ForEach-Object { #walkinthrough all subfolder-paths
#
Set-Location -Path $_.FullName
#remove existing AllInOne.csv (targed name for a merged file) in case it has been left over from a previous execution.
$FileName = ".\AllInOne.csv"
if (Test-Path $FileName) {
Remove-Item $FileName
}
#remove existing AllInOne.csv (targed name for archived files) in case it has been left over from a previous execution.
$FileName = ".\AllInOne.zip"
if (Test-Path $FileName) {
Remove-Item $FileName
}
#compressing all csv files in the current path, temporarily named AllInOne.zip. Doing that for each file adding it to the archive (with -Update)
# I wonder if there is a more efficient way to do that.
dir $_.FullName | where { $_.Extension -eq ".csv"} | foreach { Compress-Archive $_.FullName -DestinationPath "AllInOne.zip" -Update}
##########################################################
# This code is basically merging all the CSV files
# skipping the header of added files
##########################################################
$getFirstLine = $true
get-childItem ".\*.csv" | foreach {
$filePath = $_
$lines = $lines = Get-Content $filePath
$linesToWrite = switch($getFirstLine) {
$true {$lines}
$false {$lines | Select -Skip 1}
}
$getFirstLine = $false
Add-Content ".\AllInOne.csv" $linesToWrite
# Output file is named AllInOne.csv temporarily - this is not a requirement
# It was simply easier for me to come up with this temp file in the first place (symptomatic for copy&paste).
}
#########################################################
#deleting old csv files
dir $_.FullName | where { $_.Extension -eq ".csv" -and $_ -notlike "AllInOne.csv"} | foreach { Remove-Item $_.FullName}
# Temporarily rename AllinOne files with parent folder name
Get-ChildItem -Path $_.FullName -Filter *.csv | Rename-Item -NewName {$_.Basename.Replace("AllInOne",$_.Directory.Name) + $_.extension}
Get-ChildItem -Path $_.FullName -Filter *.zip | Rename-Item -NewName {$_.Basename.Replace("AllInOne",$_.Directory.Name) + $_.extension}
}
我一直在Powershell ISE中执行它。这个剧本只是一个管家的角色,随意地执行,而不是在固定的基础上执行——所以表演并不重要
如果可能的话,我更喜欢使用不依赖其他库的脚本(例如,对于Zip)。它可能不是防弹的,但我见过更糟糕的拼凑脚本。它肯定会完成你想要的工作,但是这里有一些小的改变,会使它变得更短,更难打破
Import CSV
将所有文件编译成一个数组。您不必担心剥离标题或意外删除行Export CSV-Path$\ FullName-NoTypeInformation
将所有内容输出到一个新的CSV文件中
就个人而言,我宁愿在第一次正确命名创建的文件,而不是必须返回并重命名它们,除非完全没有办法。这似乎不适合您的情况,因此您应该能够在第一次使用正确的名称创建它们。非常感谢。这很有帮助。我没有使用$csvArray,而是直接使用导出CSV进行管道导入。这对我来说更容易发现CSV中的不一致。导入CSV$124;导出CSV-路径。/AllInOne.CSV-NoTypeInformation-追加
Get-ChildItem "*.csv" | Foreach-Object {
$csvArray += Import-CSV $_
}
function CompileCompressCSV {
param (
[string] $Path
)
# Code from inside the ForEach Loop
}
# Main Script
CompileCompressCSV -Path $targetDir
Get-ChildItem -Path $targetDir -Recurse -Directory | ForEach-Object {
CompileCompressCSV -Path $_.FullName
}