Metin Dosyalarını Okumak ve Metni Değiştirmek için PowerShell'i Kullanma


Bir metin dosyasını okumak ve metni değiştirmek için PowerShell'i nasıl kullanacağınızı bilmeniz mi gerekiyor? Buna PowerShell Okuma Metni Dosyası diyoruz.

Başka yerde arama! Bu blog yazısı sizin için. Yazının sonunda size hayatınızı çok daha kolaylaştırmak için oluşturduğum bir işlevi göstereceğim.

Bir dosyadaki metni PowerShell ile değiştirmek üç adımlı bir işlemdir.

  1. Dosyayı okuma
  2. Dizeyi bulma ve değiştirme
  3. Dosyadaki değişiklikleri yazma.

Dosyayı Okumak

Öncelikle dosyayı okumanız gerekecek. Öncelikle Set-Content cmdlet'iyle bir tane oluşturalım, böylece üzerinde çalışabileceğimiz bir tane olsun.

Set-Content -Path 'C:\file.txt' -Value 'foo bar baz'

Bu dosyayı okumak için Get-Content komutunu kullanabilirsiniz. Aşağıda gösterildiği gibi Path parametresine bir metin dosyası yolu sağlayarak dosyayı okuyabilirsiniz.

$content = Get-Content -Path 'C:\file.txt'

Dizeyi Bulma ve Değiştirme

Artık dosyanın içeriğini bir dizede belleğe aldığımıza göre, dizeyi arayıp değiştirmemiz gerekiyor. Bunu yapmanın bir yolu -replace operatörünü kullanmaktır. Bu PowerShell operatörü bir dize bulur ve onu başka bir dizeyle değiştirir.

Örnek dosya içeriğini kullanarak, foo arama dizesine, dosya içeriğini şimdi foo foo baz yapacak olan bar değiştirme dizesini sağlayabiliriz.

PS> $newContent = $content -replace 'foo', 'bar'
bar bar baz

Dosyaya Yazma

Artık yeni dosya içeriklerini $newContent dosyasına kaydettiğimize göre, bu yeni içeriği tekrar dosyaya yazmamız gerekebilir. Bunu yapmanın bir yolu Set-Content komutunu kullanmaktır.

Set-Content komutu, bir dosyanın tüm içeriğini yeni bir değer atayarak değiştirir.

$newContent | Set-Content -Path 'C:\file.txt'

Artık C:\file.txt dosyasını Get-Content ile okuduğunuzda, dosyanın artık yeni içeriği içerdiğini göreceksiniz.

Açık Dosya Tanıtıcılarıyla Başa Çıkmak

Daha önce uyguladığınız adımlar çoğu zaman işe yarar. Ancak gerçek dünyada her şeyin her zaman bu şekilde sonuçlanmadığını göreceksiniz.

Bazen PowerShell'in kendisi açık olan dosyalarla uğraşmak zorunda kalacağınızı göreceksiniz. Bu, yeni içerikleri dosyaya geri yazmanızı engeller.

Bu açık dosya işleme durumunu düzeltmek için, önce diskte yeni içeriklerle geçici bir metin dosyası oluşturmanıza, orijinal dosyayı kaldırmanıza ve ardından geçici dosyayı yeniden adlandırmanıza olanak tanıyan basit bir iş akışı oluşturdum.

İşte nasıl çalıştığına dair bir örnek:

$filePath = 'C:\file.txt'
$tempFilePath = "$env:TEMP\$($filePath | Split-Path -Leaf)"
$find = 'foo'
$replace = 'bar'

(Get-Content -Path $filePath) -replace $find, $replace | Add-Content -Path $tempFilePath

Remove-Item -Path $filePath
Move-Item -Path $tempFilePath -Destination $filePath

Aşağıda, bu yaklaşımı bir dosyadaki metni bulma (değiştirmeme) yeteneğiyle birlikte kullanan, Find-InTextFile adlı benim oluşturduğum bir fonksiyonun örneği verilmiştir.

Bu işlev aynı zamanda dizeleri bulmak için daha güçlü düzenli ifade sözdizimini de kullanır. Düzenli ifadelerin, tek tırnak işaretleri, özel karakterler ve daha fazlası gibi özel karakterleri kullanarak daha esnek arama yapmanıza olanak sağladığını göreceksiniz.

Aşağıda aynı anda birden fazla dosyayı işlemek için foreach döngüsü kullandığımı da görebilirsiniz. İşlenecek bir sürü dosyanız varsa bu kullanışlı olur.

function Find-InTextFile {
    <#
    .SYNOPSIS
        Performs a find (or replace) on a string in a text file or files.
    .EXAMPLE
        PS> Find-InTextFile -FilePath 'C:\MyFile.txt' -Find 'water' -Replace 'wine'
    
        Replaces all instances of the string 'water' into the string 'wine' in
        'C:\MyFile.txt'.
    .EXAMPLE
        PS> Find-InTextFile -FilePath 'C:\MyFile.txt' -Find 'water'
    
        Finds all instances of the string 'water' in the file 'C:\MyFile.txt'.
    .PARAMETER FilePath
        The file path of the text file you'd like to perform a find/replace on.
    .PARAMETER Find
        The string you'd like to replace.
    .PARAMETER Replace
        The string you'd like to replace your 'Find' string with.
    .PARAMETER NewFilePath
        If a new file with the replaced the string needs to be created instead of replacing
        the contents of the existing file use this param to create a new file.
    .PARAMETER Force
        If the NewFilePath param is used using this param will overwrite any file that
        exists in NewFilePath.
    #>
    [CmdletBinding(DefaultParameterSetName = 'NewFile')]
    [OutputType()]
    param (
        [Parameter(Mandatory = $true)]
        [ValidateScript({Test-Path -Path $_ -PathType 'Leaf'})]
        [string[]]$FilePath,
        [Parameter(Mandatory = $true)]
        [string]$Find,
        [Parameter()]
        [string]$Replace,
        [Parameter(ParameterSetName = 'NewFile')]
        [ValidateScript({ Test-Path -Path ($_ | Split-Path -Parent) -PathType 'Container' })]
        [string]$NewFilePath,
        [Parameter(ParameterSetName = 'NewFile')]
        [switch]$Force
    )
    begin {
        $Find = [regex]::Escape($Find)
    }
    process {
        try {
            foreach ($File in $FilePath) {
                if ($Replace) {
                    if ($NewFilePath) {
                        if ((Test-Path -Path $NewFilePath -PathType 'Leaf') -and $Force.IsPresent) {
                            Remove-Item -Path $NewFilePath -Force
                            (Get-Content $File) -replace $Find, $Replace | Add-Content -Path $NewFilePath -Force
                        } elseif ((Test-Path -Path $NewFilePath -PathType 'Leaf') -and !$Force.IsPresent) {
                            Write-Warning "The file at '$NewFilePath' already exists and the -Force param was not used"
                        } else {
                            (Get-Content $File) -replace $Find, $Replace | Add-Content -Path $NewFilePath -Force
                        }
                    } else {
                        (Get-Content $File) -replace $Find, $Replace | Add-Content -Path "$File.tmp" -Force
                        Remove-Item -Path $File
                        Move-Item -Path "$File.tmp" -Destination $File
                    }
                } else {
                    Select-String -Path $File -Pattern $Find
                }
            }
        } catch {
            Write-Error $_.Exception.Message
        }
    }
}

Kaynaklar

Set-Content komutu hakkında daha fazla bilgi için Set-Content: Bir Dosyaya Yazmanın PowerShell Yolu'na veya bir dosyaya içerik yazmanın alternatif bir yoluna göz atın: Dosyadan Çıkar komutu.

İlgili makaleler