I've been a big fan of Windows Terminal since the very beginning. In fact, I've been using it for so long that I've been moving along profile settings that have long since changed. I didn't bother to update my settings. Part of the challenge is that the app will update in the background and I don't realize it. Which means I never go to look at release notes to see what has changed. The current release 0.11.1120 made some breaking changes, which I've now sorted out and my settings file is up to date and where I need it. Now, I need to keep good backups because I'm always tinkering with it. That means backup. And since I do everything in PowerShell, that means a script.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
Before I get to the script, let me mention one thing I am doing differently. The default location for the settings file is in your AppData folder.
$ENV:Userprofile\AppData\Local\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json
This is where application is looking. But I want to make sure that file is backed up AND I'd like to use it on multiple systems. So I have created a hardlink to this file that points to a copy in my OneDrive folder. You can create a symbolic link but it won't work the way you want.
Creating a hardlink to file in a different location is most likely not a supported configuration for Windows Terminal and there's no guarantee it will work with future versions. But I'm willing to accept the risk.
If you are curious, here's a PowerShell snippet that you can use (at your own risk).
$params = @{ Path = "$ENV:Userprofile\AppData\Local\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json" ItemType = "HardLink" Value = "C:\users\jeff\OneDrive\windowsterminal\settings.json" } Move-Item -Path $params.path -Destination $params.value New-Item @params
My backup script is going to use the new location but it will work with the original file as well. You will need to edit the script to meet your situation. The idea behind the script is to create numbered backups of the settings.json file like settings.bak1.json. The script has a parameter that you can use to limit the number of backup files. I'm using a default value of 7. The other parameter is the destination folder for the backup files. I'm using the same OneDrive folder.
#Backup-WTSettings.ps1 [CmdletBinding(SupportsShouldProcess)] Param( #how many backup copies should be saved [int]$Limit = 7, #backup folder [parameter(HelpMessage = "Specify the backup location")] [ValidateScript({Test-Path $_})] [string]$Destination = "C:\users\jeff\OneDrive\windowsTerminal" ) #Actual path to settings.json file - you will want to uncomment this line #$json = $ENV:Userprofile\AppData\Local\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json #comment out or update to reflect the location of the settings.json file to backup. $json = "C:\users\jeff\OneDrive\windowsterminal\settings.json" Write-Verbose "Backing up $json to $Destination" Write-Verbose "Get existing backups and save as an array sorted by name" [array]$bak = Get-ChildItem -path $Destination -Name settings.bak*.json | Sort-Object -Property name if ($bak.count -eq 0) { Write-Verbose "Creating first backup copy." [int]$new = 1 } else { #get the numeric value [int]$counter = ([regex]"\d+").match($bak[-1]).value Write-Verbose "Last backup is #$counter" [int]$new = $counter + 1 Write-Verbose "Creating backup copy $new" } $backup = Join-Path -path $Destination -ChildPath "settings.bak$new.json" Write-Verbose "Creating backup $backup" Copy-Item -Path $json -Destination $backup #update the list of backups sorted by age and delete extras Write-Verbose "Removing any extra backup files over the limit of $Limit" Get-ChildItem -path $Destination\settings.bak*.json | Sort-Object -Property LastWriteTime -Descending | Select-Object -Skip $Limit | Remove-Item #renumber backup files Write-Verbose "Renumbering backup files" <# You can't rename a file if it will conflict with an existing file so files will be copied to a temp folder with a new name, the old file deleted and then the copy restored #> Get-ChildItem -path $Destination\settings.bak*.json | Sort-Object -Property LastWriteTime | ForEach-Object -Begin {$n = 0} -process { #rename each file with a new number $n++ $temp = Join-Path -path $env:TEMP -ChildPath "settings.bak$n.json" Write-Verbose "Copying temp file to $temp" $_ | Copy-Item -Destination $temp Write-Verbose "Removing $($_.name)" $_ | Remove-Item } -end { Write-Verbose "Restoring temp files to $Destination" Get-ChildItem -Path "$env:TEMP\settings.bak*.json" | Move-Item -Destination $Destination } #show current backup files Get-ChildItem -path $Destination\settings.bak*.json | Sort-Object -Property LastWriteTime -Descending
I think the script is documented enough so that you can figure out what it is doing.
In an earlier version I realized the numbering was going to increase even though I was deleting older folders. I decided that what I really wanted was to have no more than 7 files, settings.bak1.json through settings.bak7.json, with 1 representing the oldest backup. This meant I had to rename the backup files. The tricky part was that I had rename using a filename that already existed. The easiest solution was to copy the the numbered version to a temp folder, delete the file and then copy the temp files back to my destination directory.
The script also supports -WhatIf and has Verbose output. If you have any questions about what I am doing or why, please feel free to post a comment. Enjoy and keep learning!
3 thoughts on “Backing Up Windows Terminal Settings with PowerShell”
Comments are closed.