Project import generated by Copybara.

PiperOrigin-RevId: 294477904
This commit is contained in:
Isaac Good 2020-02-11 11:09:33 -08:00
parent 123a0b935d
commit af7f6aa63f

View File

@ -15,11 +15,68 @@ Revision 2.00
Authored, revised and maintained by many Googlers. Authored, revised and maintained by many Googlers.
[TOC] <details>
<summary>Table of Contents</summary>
- [1 Background](#s1-background)
* [1.1 Which Shell to Use](#s1.1-which-shell-to-use)
- [2 Shell Files and Interpreter Invocation](#s2-shell-files-and-interpreter-invocation)
* [2.1 File Extensions](#s2.1-file-extensions)
* [2.2 SUID/SGID](#s2.2-suid-sgid)
- [3 Environment](#s3-environment)
* [3.1 STDOUT vs STDERR](#s3.1-stdout-vs-stderr)
- [4 Comments](#s4-comments)
* [4.1 File Header](#s4.1-file-header)
+ [4.1.1 $Id$](#s4.1.1-id)
+ [4.1.2 $Id$ Pros](#s4.1.2-id-pros)
+ [4.1.3 $Id$ Cons](#s4.1.3-id-cons)
+ [4.1.4 $Id$ Decision](#s4.1.4-id-decision)
* [4.2 Function Comments](#s4.2-function-comments)
* [4.3 Implementation Comments](#s4.3-implementation-comments)
* [4.4 TODO Comments](#s4.4-todo-comments)
- [5 Formatting](#s5-formatting)
* [5.1 Indentation](#s5.1-indentation)
* [5.2 Line Length and Long Strings](#s5.2-line-length-and-long-strings)
* [5.3 Pipelines](#s5.3-pipelines)
* [5.4 Loops](#s5.4-loops)
* [5.5 Case statement](#s5.5-case-statement)
* [5.6 Variable expansion](#s5.6-variable-expansion)
* [5.7 Quoting](#s5.7-quoting)
- [6 Features and Bugs](#s6-features-and-bugs)
* [6.1 ShellCheck](#s6.1-shellcheck)
* [6.2 Command Substitution](#s6.2-command-substitution)
* [6.3 Test, `[ … ]`, and `[[ … ]]`](#s6.3-tests)
* [6.4 Testing Strings](#s6.4-testing-strings)
* [6.5 Wildcard Expansion of Filenames](#s6.5-wildcard-expansion-of-filenames)
* [6.6 Eval](#s6.6-eval)
* [6.7 Arrays](#s6.7-arrays)
+ [6.7.1 Arrays Pros](#s6.7.1-arrays-pros)
+ [6.7.2 Arrays Cons](#s6.7.2-arrays-cons)
+ [6.7.3 Arrays Decision](#s6.7.3-arrays-decision)
* [6.8 Pipes to While](#s6.8-pipes-to-while)
* [6.9 Arithmetic](#s6.9-arithmetic)
- [7 Naming Conventions](#s7-naming-conventions)
* [7.1 Function Names](#s7.1-function-names)
* [7.2 Variable Names](#s7.2-variable-names)
* [7.3 Constants and Environment Variable Names](#s7.3-constants-and-environment-variable-names)
* [7.4 Source Filenames](#s7.4-source-filenames)
* [7.5 Read-only Variables](#s7.5-read-only-variables)
* [7.6 Use Local Variables](#s7.6-use-local-variables)
* [7.7 Function Location](#s7.7-function-location)
* [7.8 main](#s7.8-main)
- [8 Calling Commands](#s8-calling-commands)
* [8.1 Checking Return Values](#s8.1-checking-return-values)
* [8.2 Builtin Commands vs. External Commands](#s8.2-builtin-commands-vs-external-commands)
- [9 Conclusion](#s9-conclusion)
</details>
<a id="s1-background"></a>
## Background ## Background
<a id="s1.1-which-shell-to-use"></a>
### Which Shell to Use ### Which Shell to Use
@ -38,6 +95,8 @@ The only exception to this is where you're forced to by whatever
you're coding for. One example of this is Solaris SVR4 packages you're coding for. One example of this is Solaris SVR4 packages
which require plain Bourne shell for any scripts. which require plain Bourne shell for any scripts.
<a id="s1.1-which-shell-to-use"></a>
### When to use Shell ### When to use Shell
Shell should only be used for small utilities or simple wrapper Shell should only be used for small utilities or simple wrapper
@ -62,8 +121,12 @@ Some guidelines:
to switch languages) consider whether the code is easily to switch languages) consider whether the code is easily
maintainable by people other than its author. maintainable by people other than its author.
<a id="s2-shell-files-and-interpreter-invocation"></a>
## Shell Files and Interpreter Invocation ## Shell Files and Interpreter Invocation
<a id="s2.1-file-extensions"></a>
### File Extensions ### File Extensions
Executables should have no extension (strongly preferred) or a Executables should have no extension (strongly preferred) or a
@ -80,6 +143,8 @@ languages. This allows library files with identical purposes but
different languages to be identically named except for the different languages to be identically named except for the
language-specific suffix. language-specific suffix.
<a id="s2.2-suid-sgid"></a>
### SUID/SGID ### SUID/SGID
SUID and SGID are *forbidden* on shell scripts. SUID and SGID are *forbidden* on shell scripts.
@ -91,9 +156,12 @@ which is why we're being explicit about banning it.
Use `sudo` to provide elevated access if you need it. Use `sudo` to provide elevated access if you need it.
<a id="s3-environment"></a>
## Environment ## Environment
<a id="s3.1-stdout-vs-stderr"></a>
### STDOUT vs STDERR ### STDOUT vs STDERR
All error messages should go to `STDERR`. All error messages should go to `STDERR`.
@ -114,9 +182,12 @@ if ! do_something; then
fi fi
``` ```
<a id="s4-comments"></a>
## Comments ## Comments
<a id="s4.1-file-header"></a>
### File Header ### File Header
Start each file with a description of its contents. Start each file with a description of its contents.
@ -135,6 +206,8 @@ Example:
``` ```
<a id="s4.2-function-comments"></a>
### Function Comments ### Function Comments
Any function that is not both obvious and short must be commented. Any Any function that is not both obvious and short must be commented. Any
@ -194,6 +267,8 @@ function del_thing(arg) {
} }
``` ```
<a id="s4.3-implementation-comments"></a>
### Implementation Comments ### Implementation Comments
Comment tricky, non-obvious, interesting or important parts of your Comment tricky, non-obvious, interesting or important parts of your
@ -203,6 +278,8 @@ This follows general Google coding comment practice. Don't comment
everything. If there's a complex algorithm or you're doing something everything. If there's a complex algorithm or you're doing something
out of the ordinary, put a short comment in. out of the ordinary, put a short comment in.
<a id="s4.4-todo-comments"></a>
### TODO Comments ### TODO Comments
Use TODO comments for code that is temporary, a short-term solution, or Use TODO comments for code that is temporary, a short-term solution, or
@ -227,12 +304,15 @@ Examples:
# TODO(mrmonkey): Handle the unlikely edge cases (bug ####) # TODO(mrmonkey): Handle the unlikely edge cases (bug ####)
``` ```
<a id="s5-formatting"></a>
## Formatting ## Formatting
While you should follow the style that's already there for files that While you should follow the style that's already there for files that
you're modifying, the following are required for any new code. you're modifying, the following are required for any new code.
<a id="s5.1-indentation"></a>
### Indentation ### Indentation
Indent 2 spaces. No tabs. Indent 2 spaces. No tabs.
@ -241,6 +321,8 @@ Use blank lines between blocks to improve readability. Indentation is
two spaces. Whatever you do, don't use tabs. For existing files, stay two spaces. Whatever you do, don't use tabs. For existing files, stay
faithful to the existing indentation. faithful to the existing indentation.
<a id="s5.2-line-length-and-long-strings"></a>
### Line Length and Long Strings ### Line Length and Long Strings
Maximum line length is 80 characters. Maximum line length is 80 characters.
@ -263,6 +345,8 @@ long_string="I am an exceptionally
long string." long string."
``` ```
<a id="s5.3-pipelines"></a>
### Pipelines ### Pipelines
Pipelines should be split one per line if they don't all fit on one Pipelines should be split one per line if they don't all fit on one
@ -286,6 +370,8 @@ command1 \
| command4 | command4
``` ```
<a id="s5.4-loops"></a>
### Loops ### Loops
Put `; do` and `; then` on the same line as the Put `; do` and `; then` on the same line as the
@ -320,6 +406,8 @@ for dir in "${dirs_to_cleanup[@]}"; do
done done
``` ```
<a id="s5.5-case-statement"></a>
### Case statement ### Case statement
* Indent alternatives by 2 spaces. * Indent alternatives by 2 spaces.
@ -374,6 +462,8 @@ while getopts 'abf:v' flag; do
done done
``` ```
<a id="s5.6-variable-expansion"></a>
### Variable expansion ### Variable expansion
In order of precedence: Stay consistent with what you find; quote your In order of precedence: Stay consistent with what you find; quote your
@ -430,6 +520,8 @@ They are listed in order of precedence.
NOTE: Using braces in `${var}` is *not* a form of quoting. "Double quotes" must NOTE: Using braces in `${var}` is *not* a form of quoting. "Double quotes" must
be used *as well*. be used *as well*.
<a id="s5.7-quoting"></a>
### Quoting ### Quoting
* Always quote strings containing variables, command substitutions, spaces or * Always quote strings containing variables, command substitutions, spaces or
@ -516,14 +608,22 @@ grep -cP '([Ss]pecial|\|?characters*)$' ${1:+"$1"}
(set -- 1 "2 two" "3 three tres"; echo $#; set -- "$@"; echo "$#, $@") (set -- 1 "2 two" "3 three tres"; echo $#; set -- "$@"; echo "$#, $@")
``` ```
<a id="s6-features-and-bugs"></a>
## Features and Bugs ## Features and Bugs
<a id="s6.1-shelllint"></a>
<a id="s6.1-shellcheck"></a>
### ShellCheck ### ShellCheck
The [ShellCheck project](https://www.shellcheck.net/) identifies common bugs and The [ShellCheck project](https://www.shellcheck.net/) identifies common bugs and
warnings for your shell scripts. It is recommended for all scripts, large or warnings for your shell scripts. It is recommended for all scripts, large or
small. small.
<a id="s6.2-command-substitution"></a>
### Command Substitution ### Command Substitution
Use `$(command)` instead of backticks. Use `$(command)` instead of backticks.
@ -544,6 +644,8 @@ var="$(command "$(command1)")"
var="`command \`command1\``" var="`command \`command1\``"
``` ```
<a id="s6.3-tests"></a>
<a id="tests"></a> <a id="tests"></a>
### Test, `[ … ]`, and `[[ … ]]` ### Test, `[ … ]`, and `[[ … ]]`
@ -578,6 +680,8 @@ fi
For the gory details, see E14 at http://tiswww.case.edu/php/chet/bash/FAQ For the gory details, see E14 at http://tiswww.case.edu/php/chet/bash/FAQ
<a id="s6.4-testing-strings"></a>
### Testing Strings ### Testing Strings
Use quotes rather than filler characters where possible. Use quotes rather than filler characters where possible.
@ -664,6 +768,8 @@ if [[ "${my_var}" > 3 ]]; then
fi fi
``` ```
<a id="s6.5-wildcard-expansion-of-filenames"></a>
### Wildcard Expansion of Filenames ### Wildcard Expansion of Filenames
Use an explicit path when doing wildcard expansion of filenames. Use an explicit path when doing wildcard expansion of filenames.
@ -690,6 +796,8 @@ rm: cannot remove `./somedir': Is a directory
removed `./somefile' removed `./somefile'
``` ```
<a id="s6.6-eval"></a>
### Eval ### Eval
`eval` should be avoided. `eval` should be avoided.
@ -707,6 +815,8 @@ eval $(set_my_variables)
variable="$(eval some_function)" variable="$(eval some_function)"
``` ```
<a id="s6.7-arrays"></a>
### Arrays ### Arrays
Bash arrays should be used to store lists of elements, to avoid quoting Bash arrays should be used to store lists of elements, to avoid quoting
@ -747,6 +857,8 @@ declare -a files=($(ls /directory))
mybinary $(get_arguments) mybinary $(get_arguments)
``` ```
<a id="s6.7.1-arrays-pros"></a>
#### Arrays Pros #### Arrays Pros
* Using Arrays allows lists of things without confusing quoting * Using Arrays allows lists of things without confusing quoting
@ -755,10 +867,14 @@ mybinary $(get_arguments)
* Arrays make it possible to safely store sequences/lists of * Arrays make it possible to safely store sequences/lists of
arbitrary strings, including strings containing whitespace. arbitrary strings, including strings containing whitespace.
<a id="s6.7.2-arrays-cons"></a>
#### Arrays Cons #### Arrays Cons
Using arrays can risk a scripts complexity growing. Using arrays can risk a scripts complexity growing.
<a id="s6.7.3-arrays-decision"></a>
#### Arrays Decision #### Arrays Decision
Arrays should be used to safely create and pass around lists. In Arrays should be used to safely create and pass around lists. In
@ -768,6 +884,8 @@ avoid confusing quoting issues. Use quoted expansion
advanced data manipulation is required, shell scripting should be advanced data manipulation is required, shell scripting should be
avoided altogether; see [above](#when-to-use-shell). avoided altogether; see [above](#when-to-use-shell).
<a id="s6.8-pipes-to-while"></a>
### Pipes to While ### Pipes to While
Use process substitution or for loops in preference to piping to while. Use process substitution or for loops in preference to piping to while.
@ -833,6 +951,8 @@ while read src dest type opts rest; do
done < /proc/mounts done < /proc/mounts
``` ```
<a id="s6.9-arithmetic"></a>
### Arithmetic ### Arithmetic
Always use `(( … ))` or `$(( … ))` rather than Always use `(( … ))` or `$(( … ))` rather than
@ -915,9 +1035,12 @@ sec=30
echo $(( hr * 3600 + min * 60 + sec )) # prints 7530 as expected echo $(( hr * 3600 + min * 60 + sec )) # prints 7530 as expected
``` ```
<a id="s7-naming-conventions"></a>
## Naming Conventions ## Naming Conventions
<a id="s7.1-function-names"></a>
### Function Names ### Function Names
Lower-case, with underscores to separate words. Separate libraries with Lower-case, with underscores to separate words. Separate libraries with
@ -947,6 +1070,8 @@ The `function` keyword is extraneous when "()" is present
after the function name, but enhances quick identification of after the function name, but enhances quick identification of
functions. functions.
<a id="s7.2-variable-names"></a>
### Variable Names ### Variable Names
As for function names. As for function names.
@ -960,6 +1085,8 @@ for zone in "${zones[@]}"; do
done done
``` ```
<a id="s7.3-constants-and-environment-variable-names"></a>
### Constants and Environment Variable Names ### Constants and Environment Variable Names
All caps, separated with underscores, declared at the top of the file. All caps, separated with underscores, declared at the top of the file.
@ -991,6 +1118,8 @@ done
readonly VERBOSE readonly VERBOSE
``` ```
<a id="s7.4-source-filenames"></a>
### Source Filenames ### Source Filenames
Lowercase, with underscores to separate words if desired. Lowercase, with underscores to separate words if desired.
@ -999,6 +1128,8 @@ This is for consistency with other code styles in Google:
`maketemplate` or `make_template` but not `maketemplate` or `make_template` but not
`make-template`. `make-template`.
<a id="s7.5-read-only-variables"></a>
### Read-only Variables ### Read-only Variables
Use `readonly` or `declare -r` to ensure they're Use `readonly` or `declare -r` to ensure they're
@ -1017,6 +1148,8 @@ else
fi fi
``` ```
<a id="s7.6-use-local-variables"></a>
### Use Local Variables ### Use Local Variables
Declare function-specific variables with `local`. Declaration Declare function-specific variables with `local`. Declaration
@ -1056,6 +1189,8 @@ my_func2() {
} }
``` ```
<a id="s7.7-function-location"></a>
### Function Location ### Function Location
Put all functions together in the file just below constants. Don't hide Put all functions together in the file just below constants. Don't hide
@ -1068,6 +1203,8 @@ may be done before declaring functions.
Don't hide executable code between functions. Doing so makes the code Don't hide executable code between functions. Doing so makes the code
difficult to follow and results in nasty surprises when debugging. difficult to follow and results in nasty surprises when debugging.
<a id="s7.8-main"></a>
### main ### main
A function called `main` is required for scripts long enough A function called `main` is required for scripts long enough
@ -1087,9 +1224,12 @@ main "$@"
Obviously, for short scripts where it's just a linear flow, Obviously, for short scripts where it's just a linear flow,
`main` is overkill and so is not required. `main` is overkill and so is not required.
<a id="s8-calling-commands"></a>
## Calling Commands ## Calling Commands
<a id="s8.1-checking-return-values"></a>
### Checking Return Values ### Checking Return Values
Always check return values and give informative return values. Always check return values and give informative return values.
@ -1143,6 +1283,8 @@ if (( return_codes[1] != 0 )); then
fi fi
``` ```
<a id="s8.2-builtin-commands-vs-external-commands"></a>
### Builtin Commands vs. External Commands ### Builtin Commands vs. External Commands
Given the choice between invoking a shell builtin and invoking a Given the choice between invoking a shell builtin and invoking a
@ -1166,6 +1308,7 @@ addition="$(expr ${X} + ${Y})"
substitution="$(echo "${string}" | sed -e 's/^foo/bar/')" substitution="$(echo "${string}" | sed -e 's/^foo/bar/')"
``` ```
<a id="s9-conclusion"></a>
## Conclusion ## Conclusion