X-Git-Url: https://zdv2.bktei.com/gitweb/BK-2020-03.git/blobdiff_plain/dd9f30387a6f3e81b56ea3e86bef174422b37c77..fdf917e1ee70b612202fe10fab2e73d0ea077017:/unitproc/bktemplate.sh diff --git a/unitproc/bktemplate.sh b/unitproc/bktemplate.sh new file mode 100755 index 0000000..44d3727 --- /dev/null +++ b/unitproc/bktemplate.sh @@ -0,0 +1,379 @@ +#!/bin/bash + +# Date: 2020-05-04T16:50Z +# Author: Steven Baltakatei Sandoval +# Description: Template for bash scripts. +# Note: Use hide-show-block function to aid readability. (ex: https://www.emacswiki.org/emacs/HideShow ). + +#== Variable Initialization == + +#== Global constants == +SCRIPT_TTL=10 # Limit script life to this in seconds. +PATH="/usr/local/bin/:$PATH" # Add user binary executable directory to PATH. +PATH="/opt/bktei:$PATH" # Add 'optional' executable directory to PATH. +SCRIPT_HOSTNAME=$(hostname) # Save hostname of system running this script. +SCRIPT_VERSION="bktemplate.sh 0.0.0" # Define version of script. Used by function 'showVersion'. +SCRIPT_TIME_SHORT="$(date +%Y%m%dT%H%M%S%z)" # Save current date & time in ISO-8601 format (YYYYmmddTHHMMSS+zzzz). +SCRIPT_DATE_SHORT="$(date +%Y%m%d)" # Save current date in ISO-8601 format. + +#== Function Definitions == +echoerr() { + # Usage: echo [ arguments ] + # Description: Prints provided arguments to stderr. + # Input: unspecified + # Output: stderr + # Script function dependencies: none + # External function dependencies: echo + # Last modified: 2020-04-11T21:16Z + # Last modified by: Steven Baltakatei Sandoval + # License: GPLv3+ + # Ref./Attrib: + # [1]: # Roth, James (2010-06-07). ["How to print text to stderr instead of stdout"](https://stackoverflow.com/a/2990533). Licensed CC BY-SA 4.0. + + echo "$@" 1>&2; # Define stderr echo function. See [1]. + return 0; # Function finished. +} # Define stderr message function. +vbm() { + # Usage: vbm "DEBUG:verbose message here" + # Description: Prints verbose message ("vbm") to stderr if OPTION_VERBOSE is set to "true". + # Input: + # - OPTION_VERBOSE variable set by processArguments function. (ex: "true", "false") + # - "$@" positional arguments fed to this function. + # Output: stderr + # Script function dependencies: echoerr + # External function dependencies: echo + # Last modified: 2020-04-11T23:57Z + # Last modified by: Steven Baltakatei Sandoval + # License: GPLv3+ + # Ref./Attrib: + + if [ "$OPTION_VERBOSE" == "true" ]; then + FUNCTION_TIME=$(date --iso-8601=ns); # Save current time in nano seconds. + echoerr "[$FUNCTION_TIME] ""$@"; # Display argument text. + fi + + # End function + return 0; # Function finished. +} # Verbose message display function. +showUsage() { + # Usage: showUsage + # Description: Displays script usage information. + # Input: none + # Output: stderr + # Script function dependencies: echoerr + # External dependencies: bash (5.0.3), echo + # Last modified: 2020-05-04T16:11Z + # Last modified by: Steven Baltakatei Sandoval + # License: GPLv3+ + # Ref./Attrib.: + + echoerr "USAGE:" + echoerr " bktemplate.sh [ options ]" + echoerr + echoerr "OPTIONS:" + echoerr " -h, --help" + echoerr " Display help information." + echoerr + echoerr " --version" + echoerr " Display script version." + echoerr + echoerr " -v, --verbose" + echoerr " Display debugging info." + echoerr + echoerr " -o, --output-file [ file ]" + echoerr " Specify output file." + echoerr + echoerr " -i, --input-file [ file ]" + echoerr " Specify input file." + echoerr + echoerr " -o, --output-dir [ directory ]" + echoerr " Specify output directory." + echoerr + echoerr " -i, --input-dir [ directory ]" + echoerr " Specify input directory." + echoerr + + # End function + return 0; # Function finished. +} # Display information on how to use this script. +showVersion() { + # Usage: showVersion + # Descriptoin: Displays script version and license information. + # Input: unspecified + # Output: stderr + # Script function dependencies: echoerr + # External function dependencies: echo + # Last modified: 2020-04-11T23:57Z + # Last modified by: Steven Baltakatei Sandoval + # License: GPLv3+ + # Ref./Attrib: + + # Initialize function + vbm "DEBUG:showVersion function called." + + # Perform work + OUTPUT="$SCRIPT_VERSION" + + # Display results + echoerr "$OUTPUT"; + + # End function + vbm "DEBUG:showVersion function ended." + return 0; # Function finished. +} # Display script version. +processArguments() { + # Usage: processArguments "$@" + # Description: Processes provided arguments in order to set script option variables useful for + # changing how other functions behave. For example, it may: + # 1. Activate verbose mode + # Input: "$@" (list of arguments provided to the function) + # Output: Sets following variables used by other functions: + # OPTION_VERBOSE Indicates verbose mode enable status. (ex: "true", "false") + # DIROUT1 Path to output directory. + # FILEOUT1 Path to output file. + # DIRIN1 Path to input directory. + # FILEIN1 Path to input file. + # OPTION_FILEOUT1_OVERWRITE Indicates whether file FILEOUT1 should be overwritten (ex: "true", "false') + # Script function dependencies: + # - echoerr Displays messages to stderr. + # - vbm Displays messsages to stderr if OPTION_VERBOSE set to "true". + # External dependencies: bash (5.0.3), echo + # Last modified: 2020-05-04T14:41Z + # Last modified by: Steven Baltakatei Sandoval + # License: GPLv3+ + # Ref./Attrib.: + # [1]: Marco Aurelio (2014-05-08). "echo that outputs to stderr". https://stackoverflow.com/a/23550347 + + # Initialize function + #vbm "DEBUG:processArguments function called." + + # Perform work + while [ ! $# -eq 0 ]; do # While number of arguments ($#) is not (!) equal to (-eq) zero (0). + #1>&2 echo "DEBUG:Starting processArguments while loop." # Debug stderr message. See [1]. + #1>&2 echo "DEBUG:Provided arguments are:""$@" # Debug stderr message. See [1]. + case "$1" in + -h | --help) showUsage; exit 1;; # Display usage. + --version) showVersion; exit 1;; # Show version + -v | --verbose) OPTION_VERBOSE="true"; vbm "DEBUG:Verbose mode enabled.";; # Enable verbose mode. See [1]. + -i | --input-file) # Define input file path + if [ -f "$2" ]; then # If $2 is file that exists, set FILEIN1 to $2, pop $2. + FILEIN1="$2"; + shift; + vbm "DEBUG:Input file FILEIN1 set to:""$2"; + else + echoerr "ERROR: Specified input file does not exist:""$2"; + echoerr "Exiting."; + exit 1; + fi ;; + -I | --input-dir) # Define input directory path + if [ -d "$2" ]; then # If $2 is dir that exists, set DIRIN1 to $2, pop $2. + DIRIN1="$2"; + shift; + vbm "DEBUG:Input directory DIRIN1 set to:""$2"; + else # Display error if $2 is not a valid dir. + echoerr "ERROR:Specified input directory does not exist:""$2"; + echoerr "Exiting."; + exit 1; + fi ;; + -o | --output-file) # Define output file path + if [ -f "$2" ]; then # If $2 is file that exists, prompt user to continue to overwrite, set FILEOUT1 to $2, pop $2. + echoerr "Specified output file $2 already exists. Overwrite? (y/n):" + read m; case $m in + y | Y | yes) OPTION_FILEOUT1_OVERWRITE="true";; + n | N | no) OPTION_FILEOUT1_OVERWRITE="false";; + *) echoerr "Invalid selection. Exiting."; exit 1;; + esac + if [ "$OPTION_FILEOUT1_OVERWRITE" == "true" ]; then + FILEOUT1="$2"; + shift; + vbm "DEBUG:Output file FILEOUT1 set to:""$2"; + else + echoerr "ERORR:Exiting in order to not overwrite output file:""$FILEOUT1"; + exit 1; + fi + else + FILEOUT1="$2"; + shift; + vbm "DEBUG:Output file FILEOUT1 set to:""$2"; + fi ;; + -O | --output-dir) # Define output directory path + if [ -d "$2" ]; then # If $2 is dir that exists, set DIROUT1 to $2, pop $2 + DIROUT1="$2"; + shift; + vbm "DEBUG:Output directory DIROUT1 set to:""$2"; + else + echoerr "ERROR:Specified output directory is not valid:""$2"; + echoerr "Exiting."; + exit 1; + fi ;; + *) echoerr "ERROR: Unrecognized argument."; exit 1;; # Handle unrecognized options. See [1]. + esac + shift + done + + # End function + vbm "DEBUG:processArguments function ended." + return 0; # Function finished. +} # Evaluate script options from positional arguments (ex: $1, $2, $3, etc.). +checkExecutables() { + # Usage: checkExecutables [ command1 ] [ command2 ] [...] [ commandN ] + # Description: Checks that provided commands exist and displays those that do not exist. + # Input: + # - command names (arguments) + # Output: commands that don't exist (stderr) + # Script function dependencies: + # - echoerr for displaying errors via stderr + # - processArguments for setting OPTION_VERBOSE + # - vbm for displaying verbose messages if OPTION_VERBOSE is "true" + # External dependencies: bash (5.0.3), command + # Last modified: 2020-04-11T23:59Z + # Last modified by: Steven Baltakatei Sandoval + # License: GPLv3+ + # Ref./Attrib.: + # [1]: SiegeX (2010-12-12). ["Difference between return and exit in Bash functions."](https://stackoverflow.com/a/4419971). Licensed CC BY-SA 4.0. + # [2]: Darryl Hein (2009-12-23). ["Add a new element to an array without specifying the index in Bash"](https://stackoverflow.com/a/1951523). Licensed CC BY-SA 4.0. + # [3]: kojiro (2012-10-03). ["Convert command line arguments into an array in Bash"](https://stackoverflow.com/a/12711853) + # [4]: niieani (2016-01-12). ["How to copy an array in Bash?"](https://stackoverflow.com/a/34733375/10850071). Licensed CC BY-SA 4.0. + + # Initialize function + vbm "DEBUG:checkExecutables function called." + declare -a candidateCommandsNames # Initialize array for storing positional arguments provided to this function. + candidateCommandsNames=("$@") # Save positional arguments to variable as string. See [3]. + vbm "DEBUG:candidateCommandsNames:""$@" + vbm "DEBUG:candidateCommandsNames[0]:""${candidateCommandsNames[0]}" + vbm "DEBUG:candidateCommandsNames[1]:""${candidateCommandsNames[1]}" + vbm "DEBUG:candidateCommandsNames[2]:""${candidateCommandsNames[2]}" + declare -a outputInvalidCommandsArray # Initialize arary for storing names of invalid commands. + declare -a outputValidCommandsArray # Initialize array for storing names of valid commands. + + # Perform work + for candidateCommandName in "${candidateCommandsNames[@]}"; do # Search through all space-delimited text for valid commands. + if command -v "$candidateCommandName" 1>/dev/null 2>/dev/null; then # Check if a command is valid or not. + outputValidCommandsArray+=("$candidateCommandName") ; # See [2]. + vbm "DEBUG:Adding $candidateCommandName to outputValidCommandsArray." + else + outputInvalidCommandsArray+=("$candidateCommandName") ; # See [2]. + vbm "DEBUG:Adding $candidateCommandName to outputInvalidCommandsArray." + fi + done + + # Output results + if [ ${#outputInvalidCommandsArray[@]} -gt 0 ]; then # if number of elements in outputInvalidCommandsArray greater than 0, then display offending commands and exit 1. + echoerr "ERROR: Invalid commands found:""${outputInvalidCommandsArray[@]}"; # display invalid commands as error + exit 1; # See [1]. + elif [ ${#outputInvalidCommandsArray[@]} -eq 0 ]; then # if number of elements in outputInvalidCommandsArray equals zero, then return 0. + vbm "DEBUG: Valid commands are:""${outputValidCommandsArray[@]}"; # display valid commands if verbose mode enabled + return 0; # See [1]. + else + echoerr "ERROR: Check outputInvalidCommandsArray."; + fi + + # End function + vbm "DEBUG:checkExecutables function ended." + return 0; # Function finished. +} # Check that certain executables exist. +updateTimeConstants() { + # Usage: updateTimeConstants + # Description: Updates time-related variables for use by other scripts. + # Input: (none) + # Output: Sets following variables: + # TIME_CURRENT Current time in long ISO-8601 format. (ex: YYYY-mm-ddTHH:MM:SS+ZZZZ) + # TIME_CURRENT_SHORT Current time in short ISO-8601 format. (ex: YYYYmmddTHHMMSS+ZZZZ) + # DATE_CURRENT Current date in ISO-8601 format. (ex: YYYY-mm-dd) + # DATE_CURRENT_SHORT Current date in short ISO-8601 format. (ex: YYYYmmdd) + # DATE_TOMORROW Tomorrow's date in ISO-8601 format. (ex: YYYY-mm-dd) + # TIME_NEXT_MIDNIGHT Time of tomorrow's midnight in long (ex: YYYY-mm-ddTHH:MM:SS+ZZZZ) + # ISO-861 format. + # SEC_TIL_MIDNIGHT Seconds until next midnight. + # Script function dependencies: + # - echoerr for displaying errors via stderr + # - processArguments for setting OPTION_VERBOSE + # - vbm for displaying verbose messages if OPTION_VERBOSE is "true" + # External dependencies: bash (5.0.3), date, echo + # Last modified: 2020-04-11T23:59Z + # Last modified by: Steven Baltakatei Sandoval + # License: GPLv3+ + # Ref./Attrib.: + + # Initialize function + vbm "DEBUG:updateTimeConstants function called." + + # Perform work + TIME_CURRENT="$(date --iso-8601=seconds)" ; + TIME_CURRENT_SHORT="$(date -d "$TIME_CURRENT" +%Y%m%dT%H%M%S%z)" + DATE_CURRENT="$(date -d "$TIME_CURRENT" --iso-8601=date)" ; + DATE_CURRENT_SHORT="$(date -d "$TIME_CURRENT" +%Y%m%d)" ; + DATE_TOMORROW="$(date -d "$TIME_CURRENT next day" --iso-8601=date)" ; + TIME_NEXT_MIDNIGHT="$(date -d "$DATE_TOMORROW" --iso-8601=seconds)" ; + SECONDS_UNTIL_NEXT_MIDNIGHT="$(( $(date +%s -d "$TIME_NEXT_MIDNIGHT") - $(date +%s -d "$TIME_CURRENT") ))" ; + + # End function + vbm "DEBUG:updateTimeConstants function ended." + return 0; # Function finished. +} # Update time constants + +#== Main Program Definition == +main() { + # Usage: main "$@" # See [1]. + # Input: unspecified (note: all Global Constants declared at beginning of script assumed to be available) + # OPTION_VERBOSE (used by vbm, set by processArguments) (ex: "true", "false") + # Output: unspecified + # Script function dependencies: + # - echoerr for displaying errors via stderr + # - vbm for displaying verbose messages if OPTION_VERBOSE is "true" + # - processArguments for setting OPTION_VERBOSE + # - checkExecutables for checking that specified commands are available + # External dependencies: bash (5.0.3), echo + # Last modified: 2020-05-04T16:50Z + # Last modified by: Steven Baltakatei Sandoval + # License: GPLv3+ + # Ref./Attrib.: + # [1]: ErichBSchulz (2011-11-20). [How to correctly pass bash script arguments to functions](https://stackoverflow.com/a/8198970). Licensed CC BY-SA 4.0. + + # Initialize function + processArguments "$@" # Process arguments. + vbm "DEBUG:main function called." + vbm "DEBUG:main function arguments are:""$@" + checkExecutables "echo" "date" "cut" "awk" # Confirm that executables necessary to run are available. Exit if any fail. + + # Process inputs + if [ -v FILEIN1 ]; then # VERBOSE: Display contents of FILEIN1 if FILEIN1 has been set. + vbm "DEBUG:main function detects input file:""$FILEIN1" ; + vbm "DEBUG:contents of following file is displayed below:""$FILEIN1" ; + if [ "$OPTION_VERBOSE" == "true" ]; then # display FILEIN1 contents via cat if verbose mode specified + echoerr "========""$FILEIN1"" START""========" ; + cat "$FILEIN1" 1>&2 ; + echoerr "========""$FILEIN1"" END""========" ; + fi + fi + + # Perform work + OUTPUT="$OUTPUT""Hello world.\n" + if [ -v FILEIN1 ]; then + OUTPUT="$OUTPUT""The b2sum hash of $FILEIN1 is: $(b2sum "$FILEIN1" | awk '{print $1}').\n"; + fi + OUTPUT="$OUTPUT""The current time is:""$SCRIPT_TIME_SHORT\n" + + # Output results + echo -e "$OUTPUT" + + if [ -v FILEOUT1 ]; then # if FILEOUT1 set, write to this file. + vbm "DEBUG:main function detects output file:""$FILEOUT1" ; + echo -e "$OUTPUT" > "$FILEOUT1" ; + vbm "DEBUG:main funtion wrote OUTPUT to:""$FILEOUT1" ; + elif [ -v DIROUT1 ]; then # else if DIROUT1 set, set FILEOUT1 to timestamped filename, combine into PATHOUT1, write output to PATHOUT1. + vbm "DEBUG:main function detects output directory:""$DIROUT1" ; + FILEOUT1="$SCRIPT_TIME_SHORT"..output + PATHOUT1="$DIROUT1"/"$FILEOUT1" + echo -e "$OUTPUT" > $PATHOUT1 ; + vbm "DEBUG:main function wrote output file to:""$PATHOUT1" ; + fi + + # End function + vbm "DEBUG:main function ended." + return 0; # Function finished. +} + +#== Perform work and exit == +main "$@" # Run main function. +exit 0;