I have thousands of shared markdown notes in hundreds of repertories with yaml frontmatter. (This frontmatter at the top of the files is between two lines containing only ---
. )
The frontmatter has a variyng number of keys, of lines (ISBN, publisher... in book notes, species, genus,... in vegetable notes...). The note can contain in the body a similar key (for instance in an example of code).
E.g myUpgrader.md
:
---
title: How to upgrade the frontmatter
author: FrViPofm
date: 20230620
subject: bash
tags: bash, sed, find
---
# The markup content
some stuff...
The notes evolve and sometimes I need to upgrade the frontmatters of all the notes. Say, in the above example, changing subject into topic.
If I know that the key is near the fifth line, I can upgrade a key with the following code in myupgrader.sh
:
#!/bin/bash
d="/home/path/to/shared/MarkupNotes/"
find "$d" -type f -name '*.md' -exec sed -i "1,6s/^$1: /$2: /" {} \;
But when I don't know the length of the frontmatter and the line where the key is set, neither if the key is set, how can I indicate to sed to search the whole frontmatter and only it and make the substitution only there, without changing the body of the note?
I guess there is a way to write the sed command, but I'm not skillful enough to find it.
You can limit sed expressions to only impact lines between two patterns. I think you're looking for:
#!/bin/bash
d="/home/path/to/shared/MarkupNotes/"
find "$d" -type f -name '*.md' -exec sed -i "/^---/,/^---/ s/^$1: /$2: /" {} \;
Assuming this script is stored in "update-frontmatter.sh", then running:
sh update-frontmatter.sh subject topic
Would result in:
---
title: How to upgrade the frontmatter
author: FrViPofm
date: 20230620
topic: bash
tags: bash, sed, find
---
# The markup content
some stuff...
If the key isn't set in the frontmatter, no changes are made.