Created
November 18, 2025 23:41
-
-
Save mmguero/34173a6f47ad18192b43c551ca63b513 to your computer and use it in GitHub Desktop.
find broken anchor links in a directory of markdown (.md) files that reference each otehr
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| shopt -s extglob | |
| # Gather anchors defined in each file | |
| declare -A defined | |
| for f in *.md; do | |
| while IFS= read -r a; do | |
| defined["$f"]+="$a " | |
| done < <(grep -Po '<a name="\K[^"]+' "$f") | |
| done | |
| echo "Checking for broken anchors…" | |
| echo | |
| broken=0 | |
| for f in *.md; do | |
| # Extract matches like (file.md#Anchor) even if followed by . , : ; ! | |
| while IFS= read -r match; do | |
| inner="${match#\(}" | |
| inner="${inner%\)}" | |
| filepart="${inner%%#*}" | |
| anchor="${inner##*#}" | |
| # Determine target file | |
| if [[ "$filepart" == *.md ]]; then | |
| target_file="$filepart" | |
| elif [[ -z "$filepart" ]]; then | |
| target_file="$f" | |
| else | |
| # Something weird like a URL, skip | |
| continue | |
| fi | |
| # Does file exist? | |
| if [[ ! -f "$target_file" ]]; then | |
| echo "❌ '$f' references missing file '$target_file'" | |
| broken=1 | |
| continue | |
| fi | |
| # Does anchor exist? | |
| if [[ ! ${defined["$target_file"]} =~ (^|[[:space:]])"$anchor"([[:space:]]|$) ]]; then | |
| echo "❌ '$f' references '$target_file#$anchor' but that anchor does not exist" | |
| broken=1 | |
| fi | |
| done < <(grep -Pho '\([^()]*#[A-Za-z0-9_-]+\)' "$f") | |
| done | |
| (( broken == 0 )) && echo "✨ No broken anchors found!" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment