Skip to main content

Examples

Read the manual page for bash!
Yes, all of it - within reason. Even if you don't fully understand the material in front of you, it is good to give it a once-over just so you are aware it exists. I can't count how many times I've returned to the Bash manual page to re-read something I previously didn't understand, but had just suddenly clicked while working on some side project.

Just read the page, and know it exists. Check out my not-so-brief Introduction to Manual Pages if you are interested in learning how to reference these manual pages more efficiently and thoroughly. There is a lot more information there beyond the surface-level content.

Bash scripting is much like interacting with the bash terminal - the similarity can be easily seen in how we would split a bash command to multiple lines...

kapak@base:~$ l\
> s -la
total 76
drwxr-xr-x 9 kapak kapak  4096 Jul 28 01:24 .
drwxr-xr-x 3 root  root   4096 Jul  6 09:49 ..
-rw------- 1 kapak kapak  5423 Jul 20 18:10 .bash_history
-rw-r--r-- 1 kapak kapak   220 Jul  6 09:49 .bash_logout
-rw-r--r-- 1 kapak kapak  3771 Jul  6 09:49 .bashrc
...( Reduced Output ) ...
kapak@base:~$ ls -la
total 76
drwxr-xr-x 9 kapak kapak  4096 Jul 28 01:24 .
drwxr-xr-x 3 root  root   4096 Jul  6 09:49 ..
-rw------- 1 kapak kapak  5423 Jul 20 18:10 .bash_history
-rw-r--r-- 1 kapak kapak   220 Jul  6 09:49 .bash_logout
-rw-r--r-- 1 kapak kapak  3771 Jul  6 09:49 .bashrc
...( Reduced Output ) ...

In a bash script, we would handle splitting printf across multiple lines much the same - 

printf "\nYour local .vimrc has been stashed in $PWD/config-vim/backup/"\
       "\nWARNING: Running this script multiple times will result in"\
       " overwriting this backup!"
Printf Formatting

This is just one of many commands in bash, but you will use it a lot so getting to know the syntax well will make your life a lot easier. Read the below script carefully, and you will have a basic understanding of how printf can be used dynamically within scripts to provide consistent formatting.

#/bin/bash
divider===============================
divider=$divider$divider

header="\n %-10s %8s %10s %11s\n"
format=" %-10s %08d %10s %11.2f\n"

width=43

printf "$header" "ITEM NAME" "ITEM ID" "COLOR" "PRICE"

printf "%$width.${width}s\n" "$divider"

printf "$format" \
Triangle 13  red 20 \
Oval 204449 "dark blue" 65.656 \
Square 3145 orange .7

# https://linuxconfig.org/bash-printf-syntax-basics-with-examples
 
Examples

Check out my snippet repository for more up-to-date scripts, configurations - /shaunrd0/klips
Basic script example, found with the Pi book on Knoats - Staging Configs to a USB

#!/bin/bash
##Unstash.sh script using stashed settings for custom MM
##Unpacks stashed settings copied by stash.sh
##Used to prevent loss of working configs if unstash.sh fails
##To return to last working state,format the pi and run unpack.sh
##Use repack.sh and unpack.sh to backup working builds
###############################################################################

printf "\nDo you want to setup stashed PI settings?\n"
read Pi

if [ $Pi == 'Y' ]||[ $Pi == 'y' ]
then
        sudo cp -vu $DIR/wpa_supplicant.conf /etc/wpa_supplicant/
        sudo cp -vu $DIR/ssh_config /etc/ssh/
        sudo cp -vu $DIR/sshd_config /etc/ssh/
        sudo cp -vur $DIR/.ssh/ $HOME
        sudo systemctl restart ssh.service sshd.service
        #sshd fails to restart on Debian / PI?
fi

printf "\nDo you want to install MagicMirror?\n"
read Script

if [ $Script == 'y' ] || [ $Script == 'Y' ]
then
        printf "\nInstalling Magic Mirror using custom unstash script....\n\n"


        printf "\ncurl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -\n"
        curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -

        printf "\nsudo apt install -y nodejs\n"
        sudo apt install -y nodejs

        printf "\nsudo npm install pm2 -g\n"
        sudo npm install pm2 -g

        printf "\nsudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u $USER --hp /home/pi\n"
        sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u $USER --hp $HOME

        printf "\nsudo git clone https://github.com/michmich/magicmirror\n"
        sudo git clone https://github.com/MichMich/MagicMirror

        printf "\nnpm install\n"
        cd $HOME/MagicMirror && sudo npm install
        cd

        printf "unstash.sh magic mirror install complete.\nMagic Mirror installed! Navigate to ~/magicmirror/ and run the following to start manually:\nnpm start\n\n"
fi

printf "\nCopy stashed Magic Mirror configs?\n"
read Configs

if [ "$Configs" == "y" ] || ["$Configs" == "Y" ]
then
        # I can't remember why I didnt specify a root for stash/ here
        # Stick $DIR here if needed, I think it is
        sudo cp -ruv  /stash/MagicMirror/* $HOME/magicmirror/
        sudo cp -vu /mm.sh $HOME
        sudo chmod a+x mm.sh
fi

#Regardless of path, show useful help text, script finished
pm2 startup
printf "\n###########Important Instructions###########\nBe sure to also run the following to save pm2 status:\npm2 save\nTo see pm2 command examples, run -h or pm2 examples:\npm2 -h\npm2 examples\n\nRUN COMMAND BELOW TO START MAGIC MIRROR:\n\npm2 start mm.sh\n"

Do something in a subshell (a background shell) -

$ (cd /var/log && cp -- *.log ~/Desktop)

While loop using conditionals within bash to automate cmake builds -

#!/bin/bash
## Author: Shaun Reed | Contact: shaunrd0@gmail.com | URL: www.shaunreed.com ##
## A custom bash script for building cmake projects.                         ##
## Intended to be ran in root directory of the project alongside CMakeLists  ##
###############################################################################

# Infinite while loop - break on conditions
while true
do

  printf "\nEnter 1 to build, 2 to cleanup previous build, 0 to exit.\n"
  read bChoice

  # Build loop
  # If input read is == 1
  if [ $bChoice -eq 1 ]
  then
    mkdir build
    # Move to a different directory within a subshell and build the project
    # The '(' and ')' here preserves our working directory
    (cd build && cmake .. && cmake --build .)
  fi

  # Clean-up loop
  # If input read is == 2
  if [ $bChoice -eq 2 ]
  then
    printf "test\n"
    rm -Rv build/*
  fi

  # Exit loops, all other input - 

  # If input read is >= 3, exit
  if [ $bChoice -ge 3 ]
  then
    break 
  fi
  
  # If input read is <= 0, exit
  if [ $bChoice -le 0 ]
  then
    break
  fi

  # Bash will print an error if symbol or character input

done​