Coding style used for my bash projects (v2 Sep 2015) ++++ Header Always use the following header ----BEGIN HEADER #!/usr/bin/env bash PROGRAM="program-name" # Long description AUTHOR="(L) 20XX-20YY by Orsiris \"Ozy\" de Jong" CONTACT="http://www.example.com me@example.com" PROGRAM_BUILD=YYYYMMDDVV ## Optional instructions ----END HEADER Using bind style versionning: YYYYMMDDVV (Year, Month, Day, Revision): Example: 2015012402 = 2nd revision of 24 Jan 2015 ++++ Indentation Using tabs Transform old shell scripts using unexpand command ++++ Comments Some command # comment ## Some comment on a new line ################################################# Some separation ++++ Work comments Whenever there is some idea to postpone, use #TODO:dev-name: some remark A marker must be left where on the line a dev is working (when the work isn't finished). Marker is #WIP:dev-name: some remark dev-name is mandatory if more than one person is coding ++++ Pre-processor comments As debug / production environments cannot be set with bash, debug code can be removed easily by: - Removing all lines containting comment #__WITH_PARANOIA_DEBUG - Removing everying between comment #__BEGIN_WITH_PARANOIA_DEBUG and #__END_WITH_PARANOIRA_DEBUG ++++ Variables All local variables are lowercase, separated by _ (ex: low_wait) All global variables full upercase, separated by _ (ex: EXEC_TIME) All environment variables (verbose, silent, debug, etc) have prefix _ and are full upercase, separated by _ (ex: _PARANOIA_DEBUG) ++++ Functions Every word in a function begins with an uppercase (ex: SomeFunctionDoesThings) Define functions this way. Use sed ':a;N;$!ba;s/\n{\n/ {\n/g' to adapt when opening bracket is on a new line. function something { } If function has some arguments, use local variable names that are more readable than $1...$n. Explain via comments what those variables contain if needed. function anotherthing { local var_name="${1}" local other_var_name="${2}" # This variable contains stuff } Functions should always have return status function thirdthing { some_command return $? } ++++ Sub functions When a function is a subroutine of another function, it is called _SomethingAsSubFunction ++++ Function argument check Bash does not provide any checks against missing function arguments. Also, missing quotes can lead to an inconsistent number of arguments. Every function call will be checked by __CheckArguments which takes the number of arguments, $# (the real number of args given), the parent function name and the parent function's arguments. __CheckArguments will trigger a critical error if number of arguments if incorrect. This will also prevent silent typo errors. Ex: function Something { local some="${1}" local other="${2}" local args="${3}" __CheckArguments 3 $# $FUNCNAME "$*" __CheckArguments will only trigger if script is called with DEBUG=yes Also, with PARANOIA_DEBUG=yes, __CheckArguments will recount all arguments given by "$*" and compare. This can mislead if arguments contain spaces. ++++ If statements If statements will be fully written (word "if" must be used). then is written on the same line. (Use sed ':a;N;$!ba;s/]\n\t*then/]; then/g' to convert files to this format... Replace "],new line, zero or more tabs, then" by "; then") if [ something ]; then stuff else other stuff fi ++++ Logging A logging function is available with the following levels of logging: - DEBUG: Only log this when DEBUG flas is set in program. Any command forged for eval should be logged by this. - NOTICE: Standard messages - WARN: Requires attention - ERROR: Program produced an error but continues execution - CRITICAL: Program execution is halted ++++ Eval The eval command should always contain 2>1&. There's a special case where this is needed: eval "some;commands" 2>> "$LOG_FILE" in order to get error messages into the log.