PowerShell globbing mangles Expo Router [id] file paths
Reading and writing files at bracketed paths like app/[id]/index.tsx failed because PowerShell treats [id] as a wildcard character class.
The symptom
On Windows, scripting against Expo Router files broke whenever the path contained a dynamic-route segment. Something like app/(app)/group/[id]/index.tsx would not read, would not write, or would silently hit the wrong file, while the same operation worked on every path without brackets.
What was happening
PowerShell’s path parameters are wildcard-expanded by default, and [id] is a valid wildcard: a character class matching one character from the set i, d. So when a cmdlet that expands wildcards (Get-Content, Set-Content, Out-File, Test-Path) sees [id] in the path, it globs it instead of treating it as a literal directory name. The bracketed segment never matches the real folder, so the operation fails or resolves somewhere unexpected.
# Looks fine. Actually globs [id] as a wildcard and misses the real file.
Get-Content "app/(app)/group/[id]/index.tsx"
This bites any framework with bracketed dynamic segments: Expo Router [id], Next.js [slug], and the catch-all [...rest] variants.
The fix
Use the .NET File API, which does no wildcard expansion and takes the string as a literal path:
$path = "app/(app)/group/[id]/index.tsx"
$content = [System.IO.File]::ReadAllText($path)
[System.IO.File]::WriteAllText($path, $content)
If you would rather stay in cmdlets, pass -LiteralPath instead of the positional -Path, which tells PowerShell to skip wildcard interpretation:
Get-Content -LiteralPath "app/(app)/group/[id]/index.tsx"
Set-Content -LiteralPath "app/(app)/group/[id]/index.tsx" -Value $content
Either way, [id] is treated as the folder name it is.
The lesson
PowerShell path parameters are wildcard-expanded by default, so bracketed paths from Expo Router or Next.js dynamic routes break unless you use -LiteralPath or the .NET File API.
Discussion
Powered by GitHub. Sign in to leave a comment.