Learn Docker With My Newest Course

Dive into Docker takes you from "What is Docker?" to confidently applying Docker to your own projects. It's packed with best practices and examples. Start Learning Docker →

Shell Script: Yes / No Prompt, Heredoc, in Place Edits and More


In this video we'll go over a practical example of how I used all of these features in a project renaming shell script.

Quick Jump: Going Over a Project Rename Script

I recently created a shell script to help rename your project in my Docker + Flask starter kit. I thought it would be fun to make a video around the script itself because it covers a couple of patterns I find myself Googling all the time.

Going Over a Project Rename Script


  • 0:54 – The short version on why I created this script
  • 2:02 – Running the script to get an idea of how it works
  • 3:43 – Ensuring variables are set and are what we expect
  • 4:47 – Creating multi-line strings using a heredoc
  • 6:12 – Choosing to use printf for a multi-line string in one case
  • 9:13 – Running a sub-shell and doing variable interpolation inside of a heredoc
  • 10:03 – Creating a yes / no prompt that only accepts Yy or Nn
  • 11:40 – Adding -r to the read command to make ShellCheck happy
  • 12:39 – Another yes / no prompt for initializing a git repo
  • 13:26 – Doing a cross platform recursive find / replace in files on Linux and macOS
  • 17:32 – How I went from doing this manually to making a script and refactoring it a bit
  • 18:33 – Getting trolled by your brain before you sleep
  • 19:56 – A quick recap on how set -e and set -o pipefail works

Code snippets

Here’s a few examples taken from the video:

Making sure variables are set

In this case both variables are coming in as command line arguments to the script. We want them both to be set before continuing with the script.

if [ -z "${APP_NAME}" ] || [ -z "${MODULE_NAME}" ]; then
    echo "You must supply both an app and module name, example: ${0} myapp MyApp"
    exit 1

This lets you create multi-line strings in a what you see is what you get way.

cat << EOF
When renaming your project you'll need to re-create a new database.

This can easily be done with Docker, but before this script does it
please agree that it's ok for this script to delete your current
project's database(s) by removing any associated Docker volumes.

Yes / No prompt

This will only accept YyNn as answers. Entering in any other characters will cause it to loop back around and ask the question again.

while true; do
    read -p "Run docker-compose down -v (y/n)? " -r yn
    case "${yn}" in
        [Yy]* ) docker-compose down -v; break;;
        [Nn]* ) exit;;
        * ) echo "";;
Default to the main branch with git

Here’s one way to do it without depending on having a modern version of git installed.

git init
git symbolic-ref HEAD refs/heads/main

As soon as you add and commit files you’ll see them on the main branch.

Recursive find / replace

The only thing I changed based on the video is using hard coded strings to make it easier to re-use this example.

find . -type f -exec perl -i -pe "s/oldname/newname/g" {} +

It’s worth pointing out that this works the same on Linux and macOS which IMO makes this better than using sed -i. That’s because sed -i on macOS works different than Linux due to macOS not using the GNU version of sed.

What are you planning to do for your next shell script? Let me know below.

Never Miss a Tip, Trick or Tutorial

Like you, I'm super protective of my inbox, so don't worry about getting spammed. You can expect a few emails per month (at most), and you can 1-click unsubscribe at any time. See what else you'll get too.