Yq Frontmatter Manipulation
Using yq to read and modify YAML frontmatter in markdown files.
yq can process YAML front matter in markdown files (Jekyll, Hugo, Obsidian) using the --front-matter flag. This is useful for batch operations across a vault or content directory.
The —front-matter Flag
Two modes are available:
| Mode | Flag | Behavior |
|---|---|---|
| Process | --front-matter=process | Modify YAML, preserve rest of file |
| Extract | --front-matter=extract | Output only the YAML, discard content |
Reading Frontmatter
Extract All Frontmatter
yq --front-matter=extract '.' pokemon.md
Read Specific Field
yq --front-matter=extract '.title' pokemon.md
yq --front-matter=extract '.tags' pokemon.md
yq --front-matter=extract '.stats.hp' pokemon.md
Check if Field Exists
yq --front-matter=extract 'has("publish")' pokemon.md
yq --front-matter=extract '.publish // false' pokemon.md
Modifying Frontmatter
Update a Field (Preserve Content)
yq --front-matter=process '.title = "Pikachu Guide"' pokemon.md
Update In-Place
yq --front-matter=process -i '.publish = true' pokemon.md
yq --front-matter=process -i '.rating = 8' pokemon.md
Add New Field
yq --front-matter=process -i '.region = "Kanto"' pokemon.md
Add to Array
yq --front-matter=process -i '.tags += ["legendary"]' pokemon.md
Delete Field
yq --front-matter=process -i 'del(.draft)' pokemon.md
Batch Operations
yq only processes the first file when given multiple arguments. Use find with -exec for batch operations:
Update All Markdown Files
find . -name "*.md" -exec yq --front-matter=process -i '.updated = now' {} \;
Set Publish to True
find ./pokemon -name "*.md" -exec yq --front-matter=process -i '.publish = true' {} \;
Add Tag to All Files
find . -name "*.md" -exec yq --front-matter=process -i '.tags += ["pokemon"]' {} \;
Update Field in Specific Directory
find ./Machine\ Learning -name "*.md" \
-exec yq --front-matter=process -i '.category = "ml"' {} \;
Extracting Data Across Files
List All Titles
for f in *.md; do
echo "$f: $(yq --front-matter=extract '.title' "$f")"
done
Find Files Missing a Field
for f in *.md; do
if [ "$(yq --front-matter=extract 'has("publish")' "$f")" = "false" ]; then
echo "Missing publish: $f"
fi
done
List Files with publish: true
for f in *.md; do
if [ "$(yq --front-matter=extract '.publish' "$f")" = "true" ]; then
echo "$f"
fi
done
Practical Examples
Add Missing Title from Filename
for f in *.md; do
title=$(basename "$f" .md)
if [ "$(yq --front-matter=extract 'has("title")' "$f")" = "false" ]; then
yq --front-matter=process -i ".title = \"$title\"" "$f"
fi
done
Standardize Date Format
find . -name "*.md" -exec yq --front-matter=process -i \
'.created = (.created | strftime("%Y-%m-%d"))' {} \;
Convert Tags String to Array
yq --front-matter=process -i '.tags = [.tags]' pokemon.md
Merge New Fields
yq --front-matter=process -i '. *= {"region": "Kanto", "generation": 1}' pokemon.md
Handling Edge Cases
Files Without Frontmatter
yq treats the entire file as YAML if no frontmatter delimiters exist. Always use --front-matter=process for safety:
# Safe - won't corrupt files without frontmatter
find . -name "*.md" -exec yq --front-matter=process -i '.publish = true' {} \;
Empty Frontmatter
# Check for empty frontmatter
yq --front-matter=extract '. == null' file.md
Tips
- Always test without
-ifirst to preview changes - Use
--front-matter=processto preserve markdown content - Use
--front-matter=extractfor read-only queries - Use
find -execfor batch operations (not multiple file arguments) - Quote field values that might contain special characters
Related
Resources
- Front Matter Docs: https://mikefarah.gitbook.io/yq/usage/front-matter