Bulk Org-Mode to Github Flavored Markdown
I wanted to move my raw notes for blog post entries from org-mode into a markdown format suitable for ingestion by Jekyll. While you could do single exports of each org file, and then copy-paste as posts are written, this seemed inefficient and difficult to make after-conversion changes. So, I set about a way to convert a set of org files into a corresponding set of markdown files. My initial approach was to use elisp to bulk script the org-mode export. I then wrapped this in a shell script which moved the files to the destination folder. However, I ended up settling on an approach of using pandoc to convert the files wrapped in a shell script. This appears to be the superior approach since it only requires one script file and less variable maintenance. I’ll leave both approaches in the post on the off chance the former works better for someone.
Environment and Dependencies
- macOS
- emacs 26.1
- spacemacs
develop
branch- with org layer (contains ox-gfm)
- spacemacs
- pandoc 2.6
Initial approach (elisp + shell script)
Shell script at ~/org/export_blog.el
:
(eval-after-load "org"
'(require 'ox-gfm nil t))
;;;###autoload
(require 'org)
(defun dired-org-to-markdown ()
(let ((files
(append
(let ((default-directory "~/org/blog"))
(mapcar #'expand-file-name
(file-expand-wildcards "**/*.org")))
(let ((default-directory "~/org/blog"))
(mapcar #'expand-file-name
(file-expand-wildcards "*.org")))
)
))
(mapc
(lambda (f)
(with-current-buffer
(find-file-noselect f)
(org-gfm-export-to-markdown)))
files))
)
(dired-org-to-markdown)
Wrapping shell script, embedded at ~/org/
:
#! /bin/bash
SRC="./blog"
DEST="/Users/michael/Library/Mobile Documents/com~apple~CloudDocs/"
emacs --batch --load=export_blog.el
rsync -zarv --include="*/" --include="*.md" --exclude="*" "$SRC" "$DEST"
Notes
- I was never able to get
ox-gfm
to load properly and ended up embedding it in the script. - org files at
~/org/blog
, blog source is at/Users/michael/Library/Mobile Documents/com~apple~CloudDocs/
Final approach (pandoc shell script)
Shell script placed at ~/org/
:
#! /bin/bash
SRC="./blog"
DEST="/Users/michael/Library/Mobile Documents/com~apple~CloudDocs/blog"
SRC_ESCAPED=$(echo $SRC | sed -e 's/\.\//\\.\\\//g')
DEST_ESCAPED=$(echo $DEST | sed -e 's/\//\\\//g')
STATEMENT="s/^$SRC_ESCAPED/$DEST_ESCAPED/"
# Create mirror'd folder structure at destination
find "$SRC" -type d -exec sh -c 'echo $1 | sed -e "$0" | xargs -I}{ mkdir -p "}{"' "$STATEMENT" {} \;
# Convert each org file to markdown in the destination folder structure
find "$SRC" -iregex ".*org" -exec sh -c 'echo $1 | sed -e "s/\.org$/\.md/" -e "$0" | xargs -I}{ pandoc -s --wrap=none -f org --toc -t gfm $1 -o }{' "$STATEMENT" {} \;
This script first creates a similar folder structure to the source
folders. As a second step, it looks through the source for org files and
creates the destination md
path via substitution with sed
. If you
are interested in debugging the output paths substitution (since this
fairly specific to my setup),
try:
find "$SRC" -iregex ".*org" -exec sh -c 'echo $1 | sed -e "s/\.org$/\.md/" -e "$0"' "$STATEMENT" {} \;
It then passes these output paths to pandoc (set to use github flavored markdown with a table of contents and no line wrapping).