Markdown Header Conversion Script
tl;dr
Bulk convert Markdown headers with double underlines and underlines to hash/pound/number sign style.
Markdown Header Styles
The original Markdown spec has two different styles of headers. One style using leading #
characters and the other using -
or =
characters underneath the headers. For almost all of my documents I used the later style.
Converting Styles
As part of an update to how I use Markdown, I wanted to switch to the #
style of headers. I had a couple hundred files, so I was hoping to bulk update all of the existing documents. After some false starts, the following are a series of commands that work, using find
and sed
.
Commands
The following were run on MacOS 10.14 (Mojave) but should work on any modern Unix command line.
The find
command recursively searches for Markdown files (*.md
) and calls sed
to do a search and replace on each.
The sed
code is a little weird, but it is based off the multi-line ‘\n’ expression here and prepending a new character(s) to a line when a match is found.
The first command removes all the trailing empty lines to clean up the files and avoid any sed
errors.
find . -type f -name "*.md" -exec sed -i '' -e :a -e '/^\n*$/{$d;N;};/\n$/ba' {} \;
The second command matches with any row that has a new line followed by 3 or more =
characters and replaces them with ===
on the end of the ‘parent’ line (removing the new line).
find . -type f -name "*.md" -exec sed -i '' -e :a -e '$!N;s/\n===.*/===/;ta' -e 'P;D' {} \;
The third command matches with any row that ends in ===
, removes the characters and pre-pends the line with #
.
find . -type f -name "*.md" -exec sed -i '' -E 's/(.+)(\=\=\=)/#\ \1/g' {} \;
The fourth and fifth commands repeat the above, but for -
characters, replacing them with a pre-pended##
.
find . -type f -name "*.md" -exec sed -i '' -e :a -e '$!N;s/\n---.*/---/;ta' -e 'P;D' {} \;
find . -type f -name "*.md" -exec sed -i '' -E 's/(.+)(\-\-\-)/##\ \1/g' {} \;
Final Script
From the command line, edit script:
vi ./markdown-updater.sh
And paste the following:
#!/bin/bash
find . -type f -name "*.md" -exec sed -i '' -e :a -e '/^\n*$/{$d;N;};/\n$/ba' {} \;
find . -type f -name "*.md" -exec sed -i '' -e :a -e '$!N;s/\n===.*/===/;ta' -e 'P;D' {} \;
find . -type f -name "*.md" -exec sed -i '' -E 's/(.+)(\=\=\=)/#\ \1/g' {} \;
find . -type f -name "*.md" -exec sed -i '' -e :a -e '$!N;s/\n---.*/---/;ta' -e 'P;D' {} \;
find . -type f -name "*.md" -exec sed -i '' -E 's/(.+)(\-\-\-)/##\ \1/g' {} \;
Finally, make executable:
sudo chmod u+x ./markdown-updater.sh
The script should be copied to the root of the directory containing Markdown files and run.