Skip to content

Instantly share code, notes, and snippets.

@jackbaty
Created June 15, 2025 11:41
Show Gist options
  • Save jackbaty/55738c9a9209c90705346fdeaf5062cc to your computer and use it in GitHub Desktop.
Save jackbaty/55738c9a9209c90705346fdeaf5062cc to your computer and use it in GitHub Desktop.
Import org-journal entries to Day One
#!/bin/bash
# Org-journal to Day One import script
# Usage: ./import_org_to_dayone.sh <org-journal-file>
#
# Written mostly by Claude, with one tweak. Here's the prompt
# I would like a bash script that will use the dayone2 command line tool to import
# my Org-journal entries into the Day One app. I've attached a sample journal
# file. The script should loop through each org heading, derive the entry date
# from the CREATED property and call the dayone2 command with that date and the
# text from the org-journal entry. The org heading should be used as the Day One
# entry's title.
set -euo pipefail
# Check if file argument is provided
if [ $# -eq 0 ]; then
echo "Usage: $0 <org-journal-file>"
echo "Example: $0 2025-04.org"
exit 1
fi
ORG_FILE="$1"
# Check if file exists
if [ ! -f "$ORG_FILE" ]; then
echo "Error: File '$ORG_FILE' not found."
exit 1
fi
# Check if dayone2 command is available
if ! command -v dayone2 &> /dev/null; then
echo "Error: dayone2 command not found. Please install Day One CLI tools."
exit 1
fi
# Function to convert YYYYMMDD to YYYY-MM-DD format
format_date() {
local date_str="$1"
echo "${date_str:0:4}-${date_str:4:2}-${date_str:6:2}"
}
# Function to process org file
process_org_file() {
local file="$1"
local current_title=""
local current_date=""
local current_content=""
local in_entry=false
local line_num=0
while IFS= read -r line || [[ -n "$line" ]]; do
((line_num++))
# Check if this is a heading line (starts with *)
if [[ "$line" =~ ^[[:space:]]*\*[[:space:]]+ ]]; then
# Process previous entry if we have one
if [ "$in_entry" = true ] && [ -n "$current_title" ] && [ -n "$current_date" ]; then
import_entry "$current_title" "$current_date" "$current_content"
fi
# Extract title (everything after the * and any spaces, but before any tags)
current_title=$(echo "$line" | sed -E 's/^[[:space:]]*\*+[[:space:]]+([^:]*).*/\1/' | sed 's/[[:space:]]*$//')
current_content=""
current_date=""
in_entry=false
# Check if this is a CREATED property line
elif [[ "$line" =~ ^[[:space:]]*:CREATED:[[:space:]]*([0-9]{8}) ]]; then
current_date="${BASH_REMATCH[1]}"
in_entry=true
# Skip other property lines and property drawer boundaries
elif [[ "$line" =~ ^[[:space:]]*: ]] || [[ "$line" =~ ^[[:space:]]*:END:[[:space:]]*$ ]]; then
continue
# Skip empty lines at the beginning of content
elif [ "$in_entry" = true ] && [ -z "$current_content" ] && [[ "$line" =~ ^[[:space:]]*$ ]]; then
continue
# Collect content lines (but skip setup and other meta lines)
elif [ "$in_entry" = true ] && ! [[ "$line" =~ ^[[:space:]]*# ]] && ! [[ "$line" =~ ^[[:space:]]*\+[A-Z] ]]; then
if [ -n "$current_content" ]; then
current_content="$current_content"$'\n'"$line"
else
current_content="$line"
fi
fi
done < "$file"
# Process the last entry
if [ "$in_entry" = true ] && [ -n "$current_title" ] && [ -n "$current_date" ]; then
import_entry "$current_title" "$current_date" "$current_content"
fi
}
# Function to import a single entry to Day One
import_entry() {
local title="$1"
local date_raw="$2"
local content="$3"
# Format date for Day One (YYYY-MM-DD)
local formatted_date=$(format_date "$date_raw")
# Clean up content (remove leading/trailing whitespace)
content=$(echo "$content" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
# Skip entries with no content
if [ -z "$content" ]; then
echo "Skipping entry '$title' - no content"
return
fi
echo "Importing: $title ($formatted_date)"
# Create temporary file for the entry content
local temp_file=$(mktemp)
# Write content to temp file
echo "$content" > "$temp_file"
# Import to Day One using dayone2 command
# Format: dayone2 -d YYYY-MM-DD new < content_file
if dayone2 -j "Org Journal" -d "$formatted_date" new < "$temp_file"; then
echo "✓ Successfully imported: $title"
else
echo "✗ Failed to import: $title"
fi
# Clean up temp file
rm "$temp_file"
}
# Main execution
echo "Starting import from $ORG_FILE to Day One..."
echo "----------------------------------------"
process_org_file "$ORG_FILE"
echo "----------------------------------------"
echo "Import complete!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment