PowerShell: набор содержимого, имеющий проблемы с "файлом, уже используемым"
Я работаю над PowerShell script, который находит все файлы с PATTERN в пределах данного DIRECTORY, распечатывает соответствующие строки документа с выделенным PATTERN, а затем заменяет PATTERN предоставленным REPLACE словом, затем сохраняет файл обратно. Поэтому он фактически редактирует файл.
Кроме того, я не могу заставить его изменить файл, потому что Windows жалуется, что файл уже открыт. Я попробовал несколько методов для решения этой проблемы, но продолжаю сталкиваться с этой проблемой. Возможно, кто-то может помочь:
param(
[string] $pattern = ""
,[string] $replace = ""
,[string] $directory ="."
,[switch] $recurse = $false
,[switch] $caseSensitive = $false)
if($pattern -eq $null -or $pattern -eq "")
{
Write-Error "Please provide a search pattern." ; return
}
if($directory -eq $null -or $directory -eq "")
{
Write-Error "Please provide a directory." ; return
}
if($replace -eq $null -or $replace -eq "")
{
Write-Error "Please provide a string to replace." ; return
}
$regexPattern = $pattern
if($caseSensitive -eq $false) { $regexPattern = "(?i)$regexPattern" }
$regex = New-Object System.Text.RegularExpressions.Regex $regexPattern
function Write-HostAndHighlightPattern([string] $inputText)
{
$index = 0
$length = $inputText.Length
while($index -lt $length)
{
$match = $regex.Match($inputText, $index)
if($match.Success -and $match.Length -gt 0)
{
Write-Host $inputText.SubString($index, $match.Index) -nonewline
Write-Host $match.Value.ToString() -ForegroundColor Red -nonewline
$index = $match.Index + $match.Length
}
else
{
Write-Host $inputText.SubString($index) -nonewline
$index = $inputText.Length
}
}
}
Get-ChildItem $directory -recurse:$recurse |
Select-String -caseSensitive:$caseSensitive -pattern:$pattern |
foreach {
$file = ($directory + $_.FileName)
Write-Host "$($_.FileName)($($_.LineNumber)): " -nonewline
Write-HostAndHighlightPattern $_.Line
%{ Set-Content $file ((Get-Content $file) -replace ([Regex]::Escape("[$pattern]")),"[$replace]")}
Write-Host "`n"
Write-Host "Processed: $($file)"
}
Проблема находится в конечном блоке кода, прямо на вызове Get-ChildItem. Конечно, некоторые из кода в этом блоке теперь немного искалечены из-за того, что я пытаюсь исправить проблему, а затем останавливаться, но помните о намерении этой части script. Я хочу получить контент, заменить слова, а затем сохранить измененный текст обратно в файл, из которого я получил его.
Любая помощь вообще будет оценена.
Ответы
Ответ 1
Убрал мой предыдущий ответ, заменив его следующим:
Get-ChildItem $directory -recurse:$recurse
foreach {
$file = ($directory + $_.FileName)
(Get-Content $file) | Foreach-object {
$_ -replace ([Regex]::Escape("[$pattern]")),"[$replace]")
} | Set-Content $file
}
Примечание:
- Скобки вокруг
Get-Content
, чтобы гарантировать, что файл разрывается за один раз (и поэтому закрыт).
- Трубопровод к последующим командам, а не к inlining.
- Некоторые из ваших команд были удалены, чтобы обеспечить простой тест.
Ответ 2
Просто предложение, но вы можете попробовать посмотреть документацию для блока кода параметров. Существует более эффективный способ обеспечения ввода параметра, если он вам нужен, и для вывода сообщения об ошибке, если пользователь этого не делает.
About_throw: http://technet.microsoft.com/en-us/library/dd819510.aspx
About_functions_advanced_parameters: http://technet.microsoft.com/en-us/library/dd347600.aspx
И тогда об использовании Write-Host все время: http://powershell.com/cs/blogs/donjones/archive/2012/04/06/2012-scripting-games-commentary-stop-using-write-host.aspx
Ответ 3
Хорошо, я наконец сел и просто набрал все последовательно в PowerShell, а затем использовал это, чтобы сделать мой script.
Это было действительно просто:
$items = Get-ChildItem $directory -recurse:$recurse
$items |
foreach {
$file = $_.FullName
$content = get-content $file
$newContent = $content -replace $pattern, $replace
Set-Content $file $newcontent
}
Спасибо всем за помощь.