使用Powershell替换多个文件中的多个字符串&文件夹 [英] Using Powershell to replace multiple strings in multiple files & folders

查看:91
本文介绍了使用Powershell替换多个文件中的多个字符串&文件夹的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 CSV 文件中的字符串列表.格式为:

I have a list of strings in a CSV file. The format is:

OldValue,NewValue
223134,875621
321321,876330
....

并且该文件包含几百行(每个 OldValue 都是唯一的).我需要处理多个文件夹中的多个文本文件的更改 &子文件夹.我对文件夹、文件和文本行数的最佳猜测是 - 15 个文件夹,每个文件夹中大约有 150 个文本文件,每个文件夹中大约有 65,000 行文本(每个文本文件在 400-500 行之间).

and the file contains a few hundred rows (each OldValue is unique). I need to process changes over a number of text files in a number of folders & subfolders. My best guess of the number of folders, files, and lines of text are - 15 folders, around 150 text files in each folder, with approximately 65,000 lines of text in each folder (between 400-500 lines per text file).

我会对数据进行 2 次传递,除非我可以一次完成.第一遍是生成一个文本文件,我将用作检查列表来查看我的更改.第二遍是实际对文件进行更改.另外,我只想更改出现字符串的文本文件(不是每个文件).

I will make 2 passes at the data, unless I can do it in one. First pass is to generate a text file I will use as a check list to review my changes. Second pass is to actually make the change in the file. Also, I only want to change the text files where the string occurs (not every file).

我正在使用以下 Powershell 脚本来浏览文件 &生成所需更改的列表.脚本运行,但速度非常慢.我还没有研究替换逻辑,但我认为它与我所拥有的相似.

I'm using the following Powershell script to go through the files & produce a list of the changes needed. The script runs, but is beyond slow. I haven't worked on the replace logic yet, but I assume it will be similar to what I've got.

# replace a string in a file with powershell
[reflection.assembly]::loadwithpartialname("Microsoft.VisualBasic") | Out-Null

Function Search {
  # Parameters $Path and $SearchString
  param ([Parameter(Mandatory=$true, ValueFromPipeline = $true)][string]$Path,
  [Parameter(Mandatory=$true)][string]$SearchString
  )
  try {
    #.NET FindInFiles Method to Look for file

    [Microsoft.VisualBasic.FileIO.FileSystem]::GetFiles(
    $Path,
    [Microsoft.VisualBasic.FileIO.SearchOption]::SearchAllSubDirectories,
    $SearchString
    )
  } catch { $_ }

}


if (Test-Path "C:\Work\ListofAllFilenamesToSearch.txt") {  # if file exists
    Remove-Item "C:\Work\ListofAllFilenamesToSearch.txt"
    }
if (Test-Path "C:\Work\FilesThatNeedToBeChanged.txt") {  # if file exists
    Remove-Item "C:\Work\FilesThatNeedToBeChanged.txt"
    }

$filefolder1 = "C:\TestFolder\WorkFiles"
$ftype = "*.txt"
$filenames1 = Search $filefolder1 $ftype

$filenames1 | Out-File "C:\Work\ListofAllFilenamesToSearch.txt" -Width 2000

if (Test-Path "C:\Work\FilesThatNeedToBeChanged.txt") {  # if file exists
    Remove-Item "C:\Work\FilesThatNeedToBeChanged.txt"
    }

(Get-Content "C:\Work\NumberXrefList.CSV" |where {$_.readcount -gt 1}) | foreach{
    $OldFieldValue, $NewFieldValue = $_.Split("|")
    $filenamelist = (Get-Content "C:\Work\ListofAllFilenamesToSearch.txt" -ReadCount 5) #| 
    foreach ($j in $filenamelist) {
    #$testvar = (Get-Content $j )
    #$testvar = (Get-Content $j -ReadCount 100)
    $testvar = (Get-Content $j -Delimiter "\n")
            Foreach ($i in $testvar)
            {
            if ($i -imatch $OldFieldValue) {
                $j + "|" + $OldFieldValue + "|" + $NewFieldValue | Out-File "C:\Work\FilesThatNeedToBeChanged.txt" -Width 2000 -Append
                }
            }
    }
}

$FileFolder = (Get-Content "C:\Work\FilesThatNeedToBeChanged.txt" -ReadCount 5)

Get-ChildItem $FileFolder -Recurse |
select -ExpandProperty fullname |
foreach {
   if (Select-String -Path $_  -SimpleMatch $OldFieldValue -Debug -Quiet) {
      (Get-Content $_) |
      ForEach-Object {$_ -replace $OldFieldValue, $NewFieldValue }|
      Set-Content $_ -WhatIf
    }
}

在上面的代码中,我用 Get-Content - default-ReadCount 尝试了几种方法-Delimiter - 试图避免内存不足错误.

In the code above, I've tried several things with Get-Content - default, with -ReadCount, and -Delimiter - in an attempt to avoid an out of memory error.

我唯一能控制的是旧 & 的长度.新的替换字符串文件.有没有办法在 Powershell 中做到这一点?有更好的选择/解决方案吗?我运行的是 Windows 7、Powershell 3.0 版.

The only thing I have control over is the length of the old & new replacement strings file. Is there a way to do this in Powershell? Is there a better option/solution? I'm running Windows 7, Powershell version 3.0.

推荐答案

您的主要问题是您一遍又一遍地阅读文件以更改每个术语.您需要反转替换项的循环和文件的循环.此外,预加载 csv.类似的东西:

Your main problem is that you're reading the file over and over again to change each of the terms. You need to invert the looping of the replace terms and looping of the files. Also, pre-load the csv. Something like:

$filefolder1 = "C:\TestFolder\WorkFiles"
$ftype = "*.txt"
$filenames = gci -Path $filefolder1 -Filter $ftype -Recurse

$replaceValues = Import-Csv -Path "C:\Work\NumberXrefList.CSV"

foreach ($file in $filenames) {
    $contents = Get-Content -Path $file

    foreach ($replaceValue in $replaceValues) {    
        $contents = $contents -replace $replaceValue.OldValue, $replaceValue.NewValue
    }

    Copy-Item $file "$file.old"
    Set-Content -Path $file -Value $contents
}

这篇关于使用Powershell替换多个文件中的多个字符串&文件夹的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆