---
title: "find, grep, awk, sed Cheatsheet"
slug: "find-grep-awk-sed"
category: "cheatsheets"
tags: ["cheatsheets", "bash", "find", "grep", "awk", "sed", "cli", "reference"]
status: "stable"
last_updated: 2026-05-14
summary: "File search and text processing with find, grep, awk, and sed: key expressions, pipelines, and globbing and escaping gotchas."
related:
  [
    "[[cheatsheets/bash-one-liners]]",
    "[[cheatsheets/regex-patterns]]",
    "[[cheatsheets/vim-commands]]",
    "[[cheatsheets/jq-syntax]]",
    "[[coding/shell]]",
    "[[cheatsheets/index|Cheatsheets]]",
  ]
---

## Overview

`find`, `grep`, `awk`, and `sed` are the four corners of Unix text processing. This card collects the expressions worth knowing, with the escaping and portability gotchas inline. For parameter expansion and pure-bash alternatives, see [[cheatsheets/bash-one-liners]].

## find

Search the filesystem before you rename, delete, or pipe.

| Expression | What it does |
| --- | --- |
| `find . -type f -name '*.md'` | All Markdown files, recursive. |
| `find . -type d -name __pycache__` | Directories named `__pycache__`. |
| `find . -type f -size +10M` | Files larger than 10 MB. |
| `find . -type f -mtime -7` | Files modified in the last 7 days. |
| `find . -type f -newer ref.txt` | Files newer than `ref.txt`. |
| `find . -type f -name '*.log' -delete` | Delete matched files in one pass. |
| `find . -type f -name '*.tmp' -exec rm {} +` | Same, batched for fewer `rm` invocations. |
| `find . -not -path '*/node_modules/*'` | Exclude a subtree. |
| `find . -type f \( -name '*.ts' -o -name '*.tsx' \)` | Multiple name patterns with OR. |
| `find . -type f -name '*.md' -print0 \| xargs -0 wc -l` | Safe pipeline for filenames with spaces. |
| `find . -mindepth 2 -maxdepth 3 -type f` | Depth-bounded search. |
| `find . -type d -empty -delete` | Remove empty directories. |

Use `-print0 | xargs -0` when filenames may contain spaces, newlines, or quotes.

## grep

Match patterns in files; use the right engine for the job.

| Flag or expression | What it does |
| --- | --- |
| `grep "pattern" file.txt` | Basic search; print matching lines. |
| `grep -r "pattern" .` | Recursive search from current directory. |
| `grep -rn "pattern" .` | Recursive with line numbers. |
| `grep -rI "pattern" .` | Skip binary files. |
| `grep -l "pattern" ./*.md` | Print only filenames, not matching lines. |
| `grep -L "pattern" ./*.md` | Files that do NOT match. |
| `grep -c "pattern" file` | Count matching lines. |
| `grep -v "pattern" file` | Invert match; print non-matching lines. |
| `grep -i "pattern" file` | Case-insensitive. |
| `grep -w "word" file` | Whole-word match. |
| `grep -A 3 -B 2 "pattern" file` | 3 lines after, 2 lines before each match. |
| `grep -E "(foo\|bar)" file` | Extended regex; equivalent to `egrep`. |
| `grep -P "\d{3}-\d{4}" file` | PCRE (not portable; GNU grep only). |
| `grep -o "pattern" file` | Print only the matched portion. |

Prefer `rg` (ripgrep) over `grep -r` for speed and `.gitignore` awareness.

## awk

`awk` is a field-oriented language; use it for columnar data.

| Expression | What it does |
| --- | --- |
| `awk '{print $1}' file` | Print first field (default delimiter: whitespace). |
| `awk '{print $NF}' file` | Print last field. |
| `awk -F: '{print $1}' /etc/passwd` | Set field delimiter to `:`. |
| `awk 'NR==5' file` | Print line 5. |
| `awk 'NR>=3 && NR<=7' file` | Print lines 3 to 7. |
| `awk '/pattern/' file` | Print lines matching a regex. |
| `awk '!/pattern/' file` | Print lines not matching. |
| `awk '{sum += $2} END {print sum}' file` | Sum column 2. |
| `awk 'BEGIN {FS=","} {print $1, $3}' file.csv` | CSV with explicit `FS`. |
| `awk '{print $2, $1}' file` | Swap columns 1 and 2. |
| `awk 'length($0) > 80' file` | Lines longer than 80 characters. |
| `awk '!seen[$0]++' file` | Remove duplicate lines (preserving order). |
| `awk '{gsub(/old/, "new"); print}' file` | Global substitution in each line. |

`awk` is ideal for log parsing and CSV reshaping when you need field access rather than full regex substitution.

## sed

`sed` edits streams line by line; use it for substitution, deletion, and insertion.

| Expression | What it does |
| --- | --- |
| `sed 's/old/new/' file` | Replace first occurrence per line. |
| `sed 's/old/new/g' file` | Replace all occurrences per line. |
| `sed -i 's/old/new/g' file` | In-place edit (GNU sed; Linux). |
| `sed -i '' 's/old/new/g' file` | In-place edit (BSD sed; macOS). |
| `sed -i.bak 's/old/new/g' file` | In-place with backup; portable. |
| `sed '/pattern/d' file` | Delete lines matching a pattern. |
| `sed -n '/start/,/end/p' file` | Print lines between two patterns. |
| `sed -n '10,20p' file` | Print lines 10 to 20. |
| `sed '1d' file` | Delete the first line (header removal). |
| `sed '$d' file` | Delete the last line. |
| `sed 's/^/PREFIX: /' file` | Prepend to every line. |
| `sed 's/$/ SUFFIX/' file` | Append to every line. |
| `sed '/pattern/a\new line' file` | Append a line after each match (GNU sed). |

## Common pipelines

Combine the tools for real-world tasks.

| Pipeline | What it does |
| --- | --- |
| `find . -name '*.log' \| xargs grep -l "ERROR"` | Find log files that contain "ERROR". |
| `grep -rn "TODO" . \| awk -F: '{print $1}' \| sort -u` | Files containing TODOs, deduplicated. |
| `find . -name '*.md' -exec grep -l "deprecated" {} +` | Markdown files with the word "deprecated". |
| `grep -r "old_function" . --include='*.py' -l \| xargs sed -i 's/old_function/new_function/g'` | Rename a function across Python files. |
| `awk '{print $1}' access.log \| sort \| uniq -c \| sort -rn \| head -10` | Top 10 IPs in an access log. |
| `sed -n '/\[ERROR\]/,/\[INFO\]/p' app.log` | Extract error blocks. |
| `find . -name '*.ts' -print0 \| xargs -0 grep -l "console.log" \| xargs sed -i '/console\.log/d'` | Remove `console.log` from TypeScript files. |

## Common gotchas

- `sed -i` is GNU; `sed -i ''` is BSD. Use `sed -i.bak` for portable in-place editing; then remove `*.bak` with `find . -name '*.bak' -delete`.
- `find . -name '*.md' -exec cmd {} ;` runs `cmd` once per file. Use `+` instead of `;` to batch files and reduce subprocess overhead.
- Unquoted globs in `-name` are expanded by the shell before `find` sees them. Always quote the pattern: `-name '*.md'`, not `-name *.md`.
- `grep -r` follows symlinks and enters `node_modules` unless you pass `--exclude-dir=node_modules`. Use `rg` to avoid this.
- `awk '{print $1}'` uses whitespace as the delimiter. A CSV with spaces inside quoted fields will be split incorrectly. Set `-F","` and handle quotes explicitly or use a proper CSV tool.
- `sed 's/./X/g'` replaces every character; `.` is a regex metacharacter. Escape it as `\.` to match a literal dot.
- `grep -P` (PCRE) is available in GNU grep but not in BSD grep. Use `-E` for ERE patterns to stay portable. For a full reference on flags that modify regex behavior across tools, see [[cheatsheets/regex-flags]].

## Related

- [[cheatsheets/bash-one-liners]]
- [[cheatsheets/regex-patterns]]
- [[cheatsheets/vim-commands]]
- [[cheatsheets/jq-syntax]]
- [[coding/shell]]
- [[cheatsheets/index|Cheatsheets]]
