sd - Intuitive Find & Replace CLI Cheatsheet
sd is a fast find-and-replace command-line tool written in Rust, designed to make the common case simple. Where sed has cryptic syntax, fragile escaping, and BSD/GNU differences, sd uses straightforward regex (or literal strings), obvious capture-group references ($1), and reads/writes files safely. For the everyday “replace X with Y across these files” task, it is far easier to get right than sed.
Installation
| Platform | Command |
|---|
| Cargo (all platforms) | cargo install sd |
| macOS (Homebrew) | brew install sd |
| Arch Linux | sudo pacman -S sd |
| Debian/Ubuntu | sudo apt install sd |
| Fedora | sudo dnf install sd |
| Verify | sd --version |
Basic Usage
sd reads stdin or files. The form is sd FIND REPLACE [FILES...].
| Command | Description |
|---|
| `echo “hello” | sd hello world` |
sd 'before' 'after' file.txt | Replace in a file (in place) |
sd 'before' 'after' *.txt | Replace across many files |
sd --help | Full option list |
Literal vs Regex
| Command | Behavior |
|---|
sd 'a.b' 'X' file | Regex: . matches any char |
sd -s 'a.b' 'X' file | Literal string (-s/--string-mode) |
sd '\d+' 'N' file | Regex digit class |
Use -s when your search text contains regex metacharacters you want treated literally — no manual escaping.
Capture Groups
sd uses simple $1, $2 references (or ${1} when adjacent to text).
# Swap "First Last" → "Last, First"
echo "Ada Lovelace" | sd '(\w+) (\w+)' '$2, $1'
# → Lovelace, Ada
# Reformat dates YYYY-MM-DD → DD/MM/YYYY
sd '(\d{4})-(\d{2})-(\d{2})' '$3/$2/$1' dates.txt
# Use braces when the group is followed by digits/letters
echo "v2" | sd 'v(\d)' 'version${1}0' # → version20
Key Options
| Option | Description |
|---|
-s, --string-mode | Treat FIND/REPLACE as literal strings |
-p, --preview | Show the diff/result without writing |
-f, --flags FLAGS | Regex flags: i (case-insensitive), m, s, etc. |
-n, --max-replacements N | Limit number of replacements |
| stdin/stdout | Omit files to act as a filter |
Regex Flags (-f)
| Flag | Effect |
|---|
i | Case-insensitive |
m | Multiline (^/$ match line boundaries) |
s | Dot matches newlines |
w | Match whole words |
# Case-insensitive replace
sd -f i 'error' 'ERROR' log.txt
Safe Preview
# See what WOULD change before touching files
sd -p 'foo' 'bar' src/*.rs
# Then apply
sd 'foo' 'bar' src/*.rs
Common Workflows
# Rename a symbol across a codebase (preview first)
sd -p 'oldFunctionName' 'newFunctionName' **/*.js
sd 'oldFunctionName' 'newFunctionName' **/*.js
# Strip trailing whitespace
sd ' +$' '' file.txt
# Replace a literal path (string mode avoids escaping the dots/slashes)
sd -s './old/path.js' './new/path.js' config.json
# Pipe usage in a chain
cat access.log | sd '\d+\.\d+\.\d+\.\d+' '[REDACTED_IP]'
sd vs sed
| Aspect | sd | sed |
|---|
| Syntax | Simple, modern regex | Terse, historical |
| Capture refs | $1, $2 | \1, \2 |
| Literal mode | -s (no escaping) | Manual escaping |
| In-place | Default for files | -i (BSD/GNU differ) |
| Streaming edits (sed-style) | Focused on replace | Full stream editor |
sd is a focused find-and-replace; for stream editing beyond substitution, sed/awk still apply. For search (not replace), pair with ripgrep.
Resources