Earth Sciences

Earth Sciences Wiki

User Tools

Site Tools


tools:style_guides:bash

These are basic style recommendations, compiled from google official style guide and other useful websites.

In order to achieve more efficient and homogeneous coding, it's been agreed that new codes submitted to the different git projects would be accepted to be committed to the master branches only if the style guide recommendations are respected. This is also a strong recommendation for your personal scripts.

File Header

The first line of your file must indicate in which language your script is written (http://en.wikipedia.org/wiki/Shebang_%28Unix%29), generally bash (#!/bin/bash). Every file must have a top-level comment including a brief overview of its contents and eventually how to use it. Author information is recommended.

Example:

#!/usr/bin/env bash
#
# ./nccf_atm_monthly.sh path_to_config_file >& EXPID-startdate.log &
#
# This script will extract variables from EC-Earth monthly atmospheric output
# which is available in MMA files, save each variable in one file and also
# combine members together. It will modify the header informaton of the
# generated files according to CMIP5 standard and the variable names will be
# modified according PCMDI standard variable names.
#
# Written by Hui Du
#
# Institut Català de Ciències del Clima / Climate Forecasting Unit (IC3/CFU)
# Created:  February 22, 2010
# Adapted: Pierre-Antoine Bretonnière - IC3 , January 2013

Indentation

Indent 2 spaces. NO TABS.

Use blank lines between blocks to improve readability. Indentation is two spaces. Whatever you do, don't use tabs. For existing files, stay faithful to the existing indentation.

Loops

Put ; do and ; then on the same line as the while, for or if.

Loops in shell are a bit different, but we follow the same principles as with braces when declaring functions. That is: ; then and ; do should be on the same line as the if/for/while. else should be on its own line and closing statements should be on their own line vertically aligned with the opening statement.

Example:

for dir in ${dirs_to_cleanup}; do
  if [[-d_dir_:_oracle_sid_]]; then
    log_date "Cleaning up old files in ${dir}/${ORACLE_SID}"
    rm "${dir}/${ORACLE_SID}/"*
    if [[_-ne_0]]; then
      error_message
    fi
  else
    mkdir -p "${dir}/${ORACLE_SID}"
    if [[_-ne_0]]; then
      error_message
    fi
  fi
done

Case statement

Indent alternatives by 2 spaces. A one-line alternative needs a space after the close parenthesis of the pattern and before the ;;. Long or multi-command alternatives should be split over multiple lines with the pattern, actions, and ;; on separate lines. The matching expressions are indented one level from the 'case' and 'esac'. Multiline actions are indented another level. In general, there is no need to quote match expressions. Pattern expressions should not be preceded by an open parenthesis. Avoid the ;& and ;;& notations.

Example:

case "${expression}" in
  a)
    variable="..."
    some_command "${variable}" "${other_expr}" ...
    ;;
  absolute)
    actions="relative"
    another_command "${actions}" "${other_expr}" ...
    ;;
  *)
    error "Unexpected expression '${expression}'" ;;
esac

Simple commands may be put on the same line as the pattern and ;; as long as the expression remains readable.

Command Substitution

Use $(command) instead of backticks.

Nested backticks require escaping the inner ones with \. The $(command) format doesn't change when nested and is easier to read.

Example:

# This is preferred:
var="$(command "$(command1)")"
 
# This is not:
var="`command \`command1\``"
</code bash>
 
====== Test, [ and [[ ======
<nowiki>[[</nowiki>
<nowiki>[[</nowiki>
Example:
 
<code bash># This ensures the string on the left is made up of characters in the
# alnum character class followed by the string name.
# Note that the RHS should not be quoted here.
# For the gory details, see
# E14 at http://tiswww.case.edu/php/chet/bash/FAQ
if [[ "filename" =~ ^+name ]]; then
 echo "Match"
fi
 
# This matches the exact pattern "f*" (Does not match in this case)
if [[_filename_f_]]; then
  echo "Match"
fi
 
# This gives a "too many arguments" error as f* is expanded to the
# contents of the current directory
if [ "filename" == f* ]; then
  echo "Match"
fi

Function and variables names

Lower-case, with underscores to separate words. Parentheses are required after the function name. The keyword function is optional, but must be used consistently throughout a project. Same thing for variables: lower-case, with underscores to separate words, with names as explicit as possible. However, constant (paths, environment variables and parameters passed through namelists) must be all caps, separated with underscores, declared at the top of the file.

Arithmetic

Never use the let command, nor use the $[…] syntax, nor use the shell helper expr. Instead, use `$1)` to perform all math operations in conjunction with the colon null utility.

When using variables, avoid using the ${var} form when possible. The shell knows to look up var as ${var}for you and omitting the ${…} leads to cleaner code. Note: this does not mean you should avoid using ${var} in non-arithmetic code.

Example

# To increment the variable "i" by one.  We avoid the ++ operator
# as it is not as portable, and this version isn't much longer.
# Note that:
#  - We do not write ${i} or $i.
#  - We put a space after the (( and before the )).
: $(( i += 1 ))
 
# To decrement the variable "i" by one:
: $(( i -= 1 ))
 
# Do some complicated math.
min=5
sec=30
echo $(( (min * 60) + sec ))

Pipelines

Pipelines (http://blog.petersobot.com/pipes-and-filters) should be split one per line if they don't all fit on one line.

If a pipeline all fits on one line, it should be on one line.

If not, it should be split at one pipe segment per line with the pipe on the newline and a 2 space indent for the next section of the pipe. This applies to a chain of commands combined using '|' as well as to logical compounds using '||' and '&&'.

Example:

# All fits on one line
command1 | command2
 
# Long commands
  command1 \
  | command2 \
  | command3 \
  | command4
1)
tools/style_guides/bash.txt · Last modified: 2018/09/07 17:14 by pechevar