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
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
}