rename.hs
Generates shell commands for safely renaming pages across the gwern.net codebase
Read this when Use this page when tracing the Haskell build pipeline, generators, metadata code, or backend utility behavior around rename.
Overview
rename.hs is a tiny code generator that produces a multi-step shell script for renaming pages on gwern.net. Renaming a page is surprisingly complex because links can appear in many different syntactic forms across markdown files, HTML includes, and configuration files. Rather than attempt the transformation directly, this script outputs a sequence of commands that the user can review and execute.
The generated script handles: git file moves, multiple link syntax variants (markdown, HTML attributes with both single and escaped double quotes), and nginx redirect configuration updates. This defensive approach ensures no link references are silently broken by a rename operation.
Public API
main :: IO ()
Reads two command-line arguments (old path, new path) and prints a shell script to stdout.
Called by: Manual invocation from command line
Calls: foo
foo :: String -> String -> IO ()
The actual script generator. Takes old and new paths (without .md extension or leading dot) and constructs a &&-chained shell command sequence.
Called by: main
Calls: putStrLn
Internal Architecture
The script is minimal—just 14 lines. It builds a single string by concatenating six shell commands:
git mv '.{old}.md' '.{new}.md' && \
gwsed.sh ' {old}' ' {new}' && \
gwsed.sh ']({old}' ']({new}' && \
gwsed.sh 'href="{old}"' 'href="{new}"' && \
gwsed.sh 'href=\"{old}\"' 'href=\"{new}\"' && \
echo '"~^{old}$" "{new}";' >> ~/wiki/static/nginx/redirect/move.conf
Each step targets a different link format:
- git mv — Move the actual file (the leading dot turns the site-absolute path like
/foointo a relative path./foo.md) - Space-prefixed — Catches references like "see /foo" in prose
- Markdown links —
](/old-path)→](/new-path) - HTML href (plain) —
href="/old-path"with regular quotes - HTML href (escaped) —
href=\"/old-path\"with backslash-escaped quotes (common in JSON/JS) - nginx redirect — Appends a regex redirect rule so old URLs still work
Key Patterns
Code generation over direct action: Rather than executing the rename itself, the script outputs commands for the user to run. This allows inspection before execution—critical since a broken rename can corrupt many files.
Pattern multiplication: The same path must be searched in multiple syntactic contexts. This is a common theme in gwern.net's tooling: content appears in markdown, HTML, and escaped forms, requiring parallel handling.
Relative path convention: The .{path}.md naming is not a hidden-file convention: page paths are given site-absolute (eg. /foo), so prepending . yields a path relative to the wiki root (./foo.md) for git mv.
Configuration
None. The script is hardcoded to:
- Assume files are
.md, addressed relative to the wiki root (.+ site-absolute path) - Use
gwsed.shfor replacements - Append redirects to
~/wiki/static/nginx/redirect/move.conf
Integration Points
Dependencies
| Tool | Purpose |
|---|---|
git | Version-controlled file moves |
gwsed.sh | Site-wide string replacement utility |
nginx.conf | Redirect rules for URL preservation |
Downstream
The generated nginx redirect rules are picked up by the web server configuration, ensuring old URLs continue to work after a rename.
Usage Example
# Generate rename script for moving "/spaced-repetition" to "/srs"
$ runghc rename.hs /spaced-repetition /srs
git mv './spaced-repetition.md' './srs.md' && gwsed.sh ' /spaced-repetition' ' /srs' && gwsed.sh '](/spaced-repetition' '](/srs' && gwsed.sh 'href="/spaced-repetition"' 'href="/srs"' && gwsed.sh 'href=\"/spaced-repetition\"' 'href=\"/srs\"' && echo '"~^/spaced-repetition$" "/srs";' >> ~/wiki/static/nginx/redirect/move.conf
# Review output, then execute
$ runghc rename.hs /spaced-repetition /srs | bash
Limitations
- Does not handle anchor/fragment references (
#section-id) - No validation that paths exist or are valid
- Assumes all files use
.mdextension - The relative path in git mv (
.{path}.md) requires running from the wiki root directory - No rollback mechanism if partial execution fails
See Also
- Utils.hs - Core utilities for string manipulation and file operations
- stringReplace.hs - Parallel string replacement utility for batch processing
- sync.sh - Build orchestrator (does not invoke rename.hs; renames are run manually)
- redirectGuesser - Generates nginx redirect rules for broken URLs
- gwern.net.conf - Nginx configuration where redirects are stored