Bugs Bunny
Bugs Bunny

Reputation: 385

PowerShell edit line in config file and save

I'm trying to edit 2 specific lines and then save, I'm having issues with the Set-Content it would overwrite everything besides the last changed line

CODE

$configPath = "C:\config.ini"

foreach($line in Get-Content $configPath) {
    if($line -like "option1" -or $line -like "option2"){
        $line -replace ("OldValue", "NewValue") | Set-Content -Path $configPath
    }
}

Upvotes: 0

Views: 3960

Answers (2)

Puzo
Puzo

Reputation: 113

The problem is that you are trying to do this on the fly. Like you are opening the file, at the same time reading its content, and during that, you are trying to write it.

So the main idea, that you will get its content to a variable first. Then the content is located inside a variable, and the file is already closed, and you can interact with its content as you do.

$configPath = "C:\config.ini"
$content = Get-Content $configPath

$newContent = $content -replace $line, "NewValue"
$newContent | Set-Content -Path $configPath

Upvotes: 1

Daniel
Daniel

Reputation: 5112

To make changes to content of a file it is generally handled by

  • getting the full contents of the file into a collection
  • modifying the collection
  • overwriting the file with the modified collection
    $configPath = "C:\config.ini"
    
    # capture both modified and unchanged lines in $newContent variable
    $newContent = foreach($line in Get-Content $configPath) {
        if($line -match "option(1|2)"){
            # modify the line
            $line -replace "OldValue", "NewValue"
        }
        else {
            # leave the line unmodified
            $line
        }
    }
    
    $newContent | Set-Content -Path $configPath

Switch is nice to use for these tasks

$configPath = "C:\config.ini"

$newContent = switch -regex -File $configPath {
    # if option1 or option2 found on line do replace and output to variable
    'option(1|2)' { $_ -replace "OldValue", "NewValue" }
    # Otherwise output line untouched
    Default { $_ }
}

$newContent | Set-Content -Path $configPath

Lastly, as Theo mentioned in comments, for ini files it might be better to use one of the existing ini modules available

Upvotes: 2

Related Questions