Showing posts with label Windows. Show all posts
Showing posts with label Windows. Show all posts

Saturday, 21 February 2026

Copy bookmarks between Edge and Canary | Powershell

I just wrote a Powershell script to copy bookmarks from one browser profile to another browser profile. In this case I copied my bookmarks in Edge Chromium
over to Google Canary. Of course, which bookmark file in which folders will vary from browser to browser and also which profile. In this case, the default profile is copied. In case your computer is used by several users, you probably want to copy a specific profile, not Default. In that case, check in file Explorer which profiles are there.

CopyBookmarksFromEdgeToCanary.ps1

<#
Edge -> Chrome Canary bookmarks copy (profile to profile)
Enhancements:
- Clear screen
- Progress bar (Write-Progress) [2](https://stackoverflow.com/questions/2688547/multiple-foreground-colors-in-powershell-in-one-command)
- Colored/emoji-rich output (Write-Host) [3](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/write-host?view=powershell-7.5)
- Counts number of bookmark URL entries by parsing Bookmarks JSON (roots + children) [1](https://jdhitsolutions.com/blog/powershell-3-0/2591/friday-fun-testing-google-chrome-bookmarks-with-powershell/)
- Measures elapsed time with Stopwatch
#>

Clear-Host

# -----------------------------
# Settings (edit these)
# -----------------------------
$edgeProfileChoice   = "Default"
$canaryProfileChoice = "Default"

# -----------------------------
# Helper: multi-color one-liner output
# -----------------------------
function Write-ColorLine {
    param(
        [string[]]$Text,
        [ConsoleColor[]]$Color,
        [switch]$NoNewLine
    )
    for ($i = 0; $i -lt $Text.Count; $i++) {
        $c = if ($i -lt $Color.Count) { $Color[$i] } else { $Color[-1] }
        Write-Host $Text[$i] -ForegroundColor $c -NoNewline
    }
    if (-not $NoNewLine) { Write-Host "" }
}

# -----------------------------
# Helper: progress stage
# -----------------------------
function Write-Step {
    param(
        [int]$Step,
        [int]$Total,
        [string]$Status
    )
    $pct = [Math]::Round(($Step / $Total) * 100, 0)
    Write-Progress -Id 0 -Activity "🧭 Edge ➜ Canary Bookmarks Migration" -Status $Status -PercentComplete $pct
}

# -----------------------------
# Helper: list profile folders that contain Bookmarks
# -----------------------------
function Get-BookmarkProfiles {
    param([string]$BasePath)

    Get-ChildItem -Path $BasePath -Directory -ErrorAction SilentlyContinue |
        Where-Object { Test-Path (Join-Path $_.FullName "Bookmarks") } |
        Select-Object -ExpandProperty Name
}

# -----------------------------
# Helper: pretty file info
# -----------------------------
function FileInfoLine {
    param([string]$Path)
    if (Test-Path $Path) {
        $fi = Get-Item $Path
        "{0}  (Size: {1:n0} bytes, LastWrite: {2})" -f $fi.FullName, $fi.Length, $fi.LastWriteTime
    } else {
        "$Path  (missing)"
    }
}

# -----------------------------
# Helper: count bookmark "url" nodes recursively in Chromium Bookmarks JSON
# -----------------------------
function Get-BookmarkUrlCount {
    param([string]$BookmarksPath)

    if (-not (Test-Path $BookmarksPath)) { return 0 }

    try {
        $json = Get-Content $BookmarksPath -Raw | ConvertFrom-Json
    } catch {
        return 0
    }

    $script:count = 0
    function Walk($node) {
        if ($null -eq $node) { return }

        if ($node.PSObject.Properties.Name -contains "type" -and $node.type -eq "url") {
            if ($node.PSObject.Properties.Name -contains "url" -and $node.url) { $script:count++ }
        }

        if ($node.PSObject.Properties.Name -contains "children" -and $node.children) {
            foreach ($child in $node.children) { Walk $child }
        }
    }

    if ($json.PSObject.Properties.Name -contains "roots") {
        foreach ($rootProp in $json.roots.PSObject.Properties) {
            Walk $rootProp.Value
        }
    }

    return $script:count
}

# -----------------------------
# Plan
# -----------------------------
$totalSteps = 9
$step = 0
$sw = [System.Diagnostics.Stopwatch]::StartNew()

Write-ColorLine -Text @("✨ ", "Bookmark mover ready", " — Edge ➜ Chrome Canary") `
               -Color @("Yellow","Green","Cyan")

$step++; Write-Step $step $totalSteps "Resolving base paths…"

$edgeUserData   = Join-Path $env:LOCALAPPDATA "Microsoft\Edge\User Data"
$canaryUserData = Join-Path $env:LOCALAPPDATA "Google\Chrome SxSata"

# (rest of script unchanged, escaped consistently)
Sample output of running the Powershell script below. The script takes around half a second to run.

✨ Bookmark mover ready — Edge ➜ Chrome Canary

πŸ“ Base paths
   Edge   : C:\Users\someuser\AppData\Local\Microsoft\Edge\User Data
   Canary : C:\Users\someuser\AppData\Local\Google\Chrome SxSata

πŸ”Ž Profiles detected (contain a 'Bookmarks' file)
   Edge   : Default
   Canary : Default

🎯 Selected profiles
   Edge   : Default
   Canary : Default

🧾 Full file paths
   Edge Bookmarks   : C:\Users\someuser\AppData\Local\Microsoft\Edge\User Data\Default\Bookmarks  (Size: 288 882 bytes, LastWrite: 20.02.2026 16:44:30)
   Canary Bookmarks : C:\Users\someuser\AppData\Local\Google\Chrome SxSata\Default\Bookmarks  (Size: 288 882 bytes, LastWrite: 20.02.2026 16:44:30)

πŸ“Š Bookmark counts (URL entries)
   Edge (source)   : 585
   Canary (target) : 585

πŸ›Ÿ Backup created: C:\Users\someuser\Desktop\BookmarkBackups\Canary_Default_Bookmarks_20260221_205353.bak


✅ Completed!
πŸ“Œ Wrote Canary Bookmarks:
   C:\Users\someuser\AppData\Local\Google\Chrome SxSata\Default\Bookmarks
πŸ“¦ Backup folder:
   C:\Users\someuser\Desktop\BookmarkBackups

πŸ“ˆ Results
   Canary before : 585 bookmarks
   Canary after  : 585 bookmarks
   Ξ” Change      : 585

⏱️ Time elapsed: 00:00.504
πŸš€ Tip: Launch Chrome Canary now — bookmarks load on startup.