在Powershell遍历子文件夹中合并CSV文件-归档和删除旧文件使用目标CSV的文件夹名称

如何解决在Powershell遍历子文件夹中合并CSV文件-归档和删除旧文件使用目标CSV的文件夹名称

我想将许多CSV文件合并为一个(几百个文件),以删除所添加CSV的标题行。

由于文件位于几个子文件夹中,因此我需要从根目录遍历所有子文件夹并在其中处理所有CSV。合并之前,我想使用zip删除旧的CSV文件来存档它们。新合并的CSV文件和zip归档文件应像其父文件夹一样命名。

如果再次为同一文件夹启动脚本,则所有已经处理的文件都不应意外损坏或删除。

我不是Powershell专家,所以我一直在从Web的多个资源中复制粘贴内容,并提出了以下解决方案(对不起,如果您知道资源,请不要随意在注释中添加引用)。 / p>

此修补程序代码可以完成任务,但感觉不是很安全。目前,它仅在子文件夹中处理CSV文件。在给定的$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)。

解决方法

它可能不是防弹的,但我看到更糟糕的是将脚本拼凑在一起。它肯定会完成您想要的工作,但是这里有一些小的更改会使它变得更短,更难破解。

  1. 由于所有文件均为CSV文件,并且文件头均相同,因此您可以使用Import-CSV将所有文件编译为一个数组。您无需担心剥离标题或意外删除行的情况。
Get-ChildItem "*.csv" | Foreach-Object {
    $csvArray += Import-CSV $_
}

然后,您可以只使用Export-CSV -Path $_.FullName -NoTypeInformation将其全部输出到新的CSV文件中。

  1. 要检查根文件夹和所有子文件夹,我会将ForEach主循环中的所有行都放入函数中,然后对根文件夹调用一次,并保留所有子文件夹的现有循环。 / li>
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
}
  1. 这更多是一种样式选择,但是我将以稍微不同的顺序执行此脚本的步骤:
    1. 获取父文件夹名称
    2. 删除旧的已编译CSV和ZIPs
    3. 将CSV编译为数组,并使用父文件夹名称输出
    4. 将CSV一起压缩成具有父文件夹名称的文件
    5. 删除所有CSV文件

就我个人而言,我宁愿在第一次使用时正确命名创建的文件,而不要返回并重命名它们,除非绝对没有办法解决。您的情况似乎并非如此,因此您应该能够在第一时间以正确的名称创建它们。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?