Search code examples
stringpowershellfilereplace

Powershell: Specific string is not removed from file when the file only contains this specific string


I am trying to remove the following string from a batch of files: "Changed database context to 'SystemLog'." by using the script below. This will work for files that contain other information besides the specific string, but not for files that only contain that specific string (the string will just remain in the file). Why does it not remove the string and just return an empty file in that case?

Input file (type = RPT File) with string and additional information:

Changed database context to 'SystemLog'.
System_Identifier_DevLog 2023-12-13 Time Actions 549 ActionsCompleted

Input file (Type = RPT File) that only contains the specific string (it does contain a new line below the string):

Changed database context to 'SystemLog'.

Code that I used:

$files=Get-ChildItem -Path "C:\SQL_SHM\Test2\" -Recurse  -File | ForEach-Object {$file = $_.FullName  (Get-Content $file ) | Where-Object {$_ -notmatch "Changed database context to 'SystemLog'."} | Set-Content $file }  #remove unnecessary text

Solution

  • When the result of filtering out that certain line is empty, piping that through to Set-Content will be a no-op, meaning nothing gets written to the file. In order to also write $null to the file in such a case, don't use the pipe, but specify the new content using the -Value parameter of Set-Content:

    $files = (Get-ChildItem -Path "C:\SQL_SHM\Test2" -Recurse -File -Filter '*.rpt').FullName
    foreach ($file in $files) {
        $newContent = Get-Content -Path $file | Where-Object {$_ -ne "Changed database context to 'SystemLog'."}
        Set-Content -Path $file -Value $newContent
    }
    

    Or, by using the much faster switch:

    $files = (Get-ChildItem -Path "C:\SQL_SHM\Test2" -Recurse -File -Filter '*.rpt').FullName
    foreach ($file in $files) {
        $newContent = switch -WildCard -File ($file) {
            "*Changed database context to 'SystemLog'.*" {}  # disregard this line
            default {$_}
        }
        Set-Content -Path $file -Value $newContent
    }