У меня есть список строк в CSV-файле. Формат:Использование Powershell для замены нескольких строк в нескольких файлах и папках
OldValue,NewValue
223134,875621
321321,876330
....
и файл содержит несколько сотен строк (каждый из которых уникален для OldValue). Мне нужно обработать изменения по нескольким текстовым файлам в нескольких папках & вложенных папок. Мое лучшее предположение о количестве папок, файлов и строк текста - 15 папок, около 150 текстовых файлов в каждой папке, с примерно 65 000 строк текста в каждой папке (между 400-500 строк в текстовом файле).
Я сделаю 2 прохода по данным, если только не могу это сделать в одном. Первый проход - создать текстовый файл, который я буду использовать в качестве контрольного списка для просмотра моих изменений. Второй проход - это фактически внести изменения в файл. Кроме того, я хочу только изменить текстовые файлы, в которых происходит строка (не каждый файл).
Я использую следующий сценарий Powershell для просмотра файлов &, чтобы получить список необходимых изменений. Сценарий запускается, но выходит за рамки медленного. Я еще не работал над логикой замены, но я предполагаю, что это будет похоже на то, что у меня есть.
# 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
- в попытке избежать отказа от ошибки памяти.
Единственное, что у меня есть, - это длина старого файла замены строк &. Есть ли способ сделать это в Powershell? Есть ли лучший вариант/решение? Я запускаю Windows 7, Powershell версии 3.0.