Script to update image embed links in Markdown files

Technology keeps moving but this post has not.
What you're about to read hasn't been updated in more than a year. The information may be out of date. Drop a comment below if you find something that needs updating.

I'm preparing to migrate this blog thingy from Hashnode (which has been great!) to a GitHub Pages site with Jekyll so that I can write posts locally and then just do a git push to publish them - and get some more practice using git in the process. Of course, I've written some admittedly-great content here and I don't want to abandon that.

Hashnode helpfully automatically backs up my posts in Markdown format to a private GitHub repo so it was easy to clone those into a local working directory, but all the embedded images were still hosted on Hashnode:

2![Clever image title](

I wanted to download those images to ./assets/images/posts-2020/ within my local Jekyll working directory, and then update the *.md files to reflect the correct local path... without doing it all manually. It took a bit of trial and error to get the regex working just right (and the result is neither pretty nor elegant), but here's what I came up with:

 2# Hasty script to process a blog post markdown file, capture the URL for embedded images,
 3# download the image locally, and modify the markdown file with the relative image path.
 5# Run it from the top level of a Jekyll blog directory for best results, and pass the 
 6# filename of the blog post you'd like to process.
 8# Ex: ./
12imageUrls=($(grep -o -P '(?<=!\[)(?:[^\]]+)\]\(([^\)]+)' $postfile | grep -o -P 'http.*'))
13imageNames=($(for name in ${imageUrls[@]}; do echo $name | grep -o -P '[^\/]+\.[[:alnum:]]+$'; done))
14imagePaths=($(for name in ${imageNames[@]}; do echo "assets/images/posts-2020/${name}"; done))
15echo -e "\nProcessing $postfile...\n"
16for index in ${!imageUrls[@]}; do
17    echo -e "${imageUrls[index]}\n => ${imagePaths[index]}"
18    curl ${imageUrls[index]} --output ${imagePaths[index]}
19    sed -i "s|${imageUrls[index]}|${imagePaths[index]}|" $postfile

I could then run that against all of the Markdown posts under ./_posts/ with:

1for post in $(ls _posts/); do ~/scripts/ $post; done

And the image embeds in the local copy of my posts now all look like this:

2![Clever image title](lhTnVwCO3.png)


More Scripts