-#!/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;