IT

특정 확장자를 가진 모든 파일을 검색하여 교체하는 PowerShell 스크립트

itgroup 2023. 4. 8. 08:24
반응형

특정 확장자를 가진 모든 파일을 검색하여 교체하는 PowerShell 스크립트

다음과 같이 중첩된 구성 파일이 몇 개 있습니다.

C:\Projects\Project_1\project1.config
  
C:\Projects\Project_2\project2.config

설정에서는 다음과 같은 문자열 치환을 수행해야 합니다.

<add key="Environment" value="Dev"/>

다음과 같이 됩니다.

<add key="Environment" value="Demo"/>

배치 스크립트를 사용할까 생각했지만 좋은 방법이 없어서 PowerShell 스크립트를 사용하면 쉽게 실행할 수 있다고 들었습니다.find/replace의 예를 찾았습니다만, C:\Projects 디렉토리내의 모든 폴더를 이동해, 확장자 「.config」로 끝나는 파일을 찾을 수 있는 방법을 찾고 있었습니다.검색 시 문자열 값을 대체해 주었으면 합니다.

이 작업을 수행하는 방법을 알아보는 데 도움이 되는 리소스나 PowerShell 전문가가 있습니까?

여기 내 머리 꼭대기에서의 첫 번째 시도가 있다.

$configFiles = Get-ChildItem . *.config -rec
foreach ($file in $configFiles)
{
    (Get-Content $file.PSPath) |
    Foreach-Object { $_ -replace "Dev", "Demo" } |
    Set-Content $file.PSPath
}

PowerShell을 선택하는 것이 좋습니다.) 지정된 디렉토리의 파일을 열거하고 읽고 처리하는 것은 매우 간단합니다.

스크립트는 다음과 같습니다.

Get-ChildItem C:\Projects *.config -recurse |
    Foreach-Object {
        $c = ($_ | Get-Content) 
        $c = $c -replace '<add key="Environment" value="Dev"/>','<add key="Environment" value="Demo"/>'
        [IO.File]::WriteAllText($_.FullName, ($c -join "`r`n"))
    }

당신이 읽을 수 있도록 코드를 더 많은 행으로 분할했습니다.SET-Content를 사용하는 대신[IO.File]::WriteAllText단, 마지막에 새로운 행이 추가됩니다.와 함께WriteAllText피할 수 있어요.

그렇지 않으면 코드는 다음과 같습니다.$c | Set-Content $_.FullName.

이 접근방식은 잘 기능합니다.

gci C:\Projects *.config -recurse | ForEach {
  (Get-Content $_ | ForEach {$_ -replace "old", "new"}) | Set-Content $_ 
}
  • "old" 및 "new"를 대응하는 값으로 변경합니다(또는 변수 사용).
  • 괄호도 잊지 마십시오. 괄호가 없으면 접근 오류가 발생합니다.

이 powershell 예에서는 폴더와 그 서브폴더에서 문자열 "\foo"의 모든 인스턴스를 찾고 "\foo"를 "\bar"로 대체하며 문자열 "\foo"를 포함하지 않는 파일을 다시 쓰지 않습니다.이 방법에서는 문자열을 찾을 수 없었던 마지막 업데이트 날짜 스탬프를 파기하지 않습니다.

Get-ChildItem  -Path C:\YOUR_ROOT_PATH\*.* -recurse 
 | ForEach {If (Get-Content $_.FullName | Select-String -Pattern '\\foo\\') 
           {(Get-Content $_ | ForEach {$_ -replace '\\foo\\', '\bar\'}) | Set-Content $_ }
           }

xml과 xpath를 사용합니다.

dir C:\Projects\project_*\project*.config -recurse | foreach-object{  
   $wc = [xml](Get-Content $_.fullname)
   $wc.SelectNodes("//add[@key='Environment'][@value='Dev']") | Foreach-Object {$_.value = 'Demo'}  
   $wc.Save($_.fullname)  
}

@Artyom님의 코멘트는 도움이 되었습니다만, 유감스럽게도 답변으로 게재되지 않았습니다.

내 생각에 이것은 받아들여진 대답의 짧은 버전이다.

ls *.config -rec | %{$f=$_; (gc $f.PSPath) | %{$_ -replace "Dev", "Demo"} | sc $f.PSPath}

파일의 텍스트를 대체하는 작은 도우미 기능을 작성했습니다.

function Replace-TextInFile
{
    Param(
        [string]$FilePath,
        [string]$Pattern,
        [string]$Replacement
    )

    [System.IO.File]::WriteAllText(
        $FilePath,
        ([System.IO.File]::ReadAllText($FilePath) -replace $Pattern, $Replacement)
    )
}

예:

Get-ChildItem . *.config -rec | ForEach-Object { 
    Replace-TextInFile -FilePath $_ -Pattern 'old' -Replacement 'new' 
}

재귀 치환을 수행할 때는 경로와 파일 이름을 포함해야 합니다.

Get-ChildItem -Recurse | ForEach {  (Get-Content $_.PSPath | 
ForEach {$ -creplace "old", "new"}) | Set-Content $_.PSPath }

현재 디렉토리의 모든 폴더 파일에서 "이전"을 대소문자를 구분하는 "새"로 바꿉니다.

언급URL : https://stackoverflow.com/questions/2837785/powershell-script-to-find-and-replace-for-all-files-with-a-specific-extension

반응형