Neat Bash Tricks

Neat Bash Tricks

Tags
Tips & Tricks
Computer Science
Software Development
Published
March 21, 2014
Author
Randall Hand
URL
I’ve been writing lots of bash scripts lately, so I thought it would be a good idea to document a few of the little tricks I’ve been using.

Force Execution

First off, to make a script that has to be executed in bash:
#!/bin/bash if [ ! "$BASH_VERSION" ] ; then   echo "Please do not use sh to run this script ($0), just execute it directly" 1>&2   exit 1 fi
 
This was needed for a script that makes uses of Bash syntax for `for` loop and some basic math, and I had a user reporting errors when they tried to do sh script.sh.  `sh` ignores the opening `#!/bin/bash` line and tries to execute the script directly, and fails when it hits those lines.
 
Then, to make a script that has to be sourced in the global environment (to set environment variables like `PATH` and `LD_LIBRARY_PATH` for the user).
 
#!/bin/bash if [[ "$(basename "$0")" == "script.sh" ]]; then   echo "ERROR: Don't run $0, source it" >&2   exit 1 fi
 
replace `script.sh` with the name of the actual file.

URL Encoding Arguments

Then, to URL Encode a parameter in bash (I used this to encode a user provided git password into the url), use this function:
rawurlencode() {   local string="${1}"   local strlen=${#string}   local encoded=""   for (( pos=0 ; pos<strlen ; pos++ )); do     c=${string:$pos:1}     case "$c" in       [-_.~a-zA-Z0-9] ) o="${c}" ;;       * )               printf -v o '%%%02x' "'$c"     esac     encoded+="${o}"   done   echo "${encoded}"    # You can either set a return variable (FASTER)   REPLY="${encoded}"   #+or echo the result (EASIER)... or both... :p }
 
Then you can use it like so:
echo Enter your GitHub username: read GIT_USER echo Enter your GitHub Password: read GIT_PASSWORD GIT_AUTH=$( rawurlencode "${GIT_USER}" ):$( rawurlencode "${GIT_PASSWORD}” ) git clone http://${GIT_AUTH}@github.com/user/repo
 
*yeah yeah, I know.. SSH keys are better… tell it to the users, not me*

GetOpt

Finally, using `getopt`.  It’s a big tool, but the basics of using it:
 
USE_SSH=0 AUTOMATED=0 BUILD_WIDTH=1 while getopts "aj:s" o; do     case "${o}" in         s)             USE_SSH=1             ;;         a)             AUTOMATED=1             ;;         j)             BUILD_WIDTH=${OPTARG}             ;;         *)             usage             ;;     esac done shift $((OPTIND-1))
 
Important bits:
 
  • the `getopts` line: Include each character recognized as a flag, and following it with a `:` if it requires an argument.
  • Then include a case for each one in the big switch.. use `$(OPTARG)` to get the argument, if it’s needed.
 
Makes argument parsing simple in bash scripts simple…  Also define a `usage` function to spew out the supported options, and you’re golden.