mirror of
https://github.com/google/styleguide.git
synced 2024-03-22 13:11:43 +08:00
Merge pull request #513 from google/change_HEAD
Update the TOC. Imported by Copybara.
This commit is contained in:
commit
f13659ba4f
145
shellguide.md
145
shellguide.md
|
@ -15,11 +15,68 @@ Revision 2.00
|
|||
|
||||
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
|
||||
|
||||
|
||||
<a id="s1.1-which-shell-to-use"></a>
|
||||
|
||||
### 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
|
||||
which require plain Bourne shell for any scripts.
|
||||
|
||||
<a id="s1.1-which-shell-to-use"></a>
|
||||
|
||||
### When to use Shell
|
||||
|
||||
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
|
||||
maintainable by people other than its author.
|
||||
|
||||
<a id="s2-shell-files-and-interpreter-invocation"></a>
|
||||
|
||||
## Shell Files and Interpreter Invocation
|
||||
|
||||
<a id="s2.1-file-extensions"></a>
|
||||
|
||||
### File Extensions
|
||||
|
||||
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
|
||||
language-specific suffix.
|
||||
|
||||
<a id="s2.2-suid-sgid"></a>
|
||||
|
||||
### SUID/SGID
|
||||
|
||||
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.
|
||||
|
||||
<a id="s3-environment"></a>
|
||||
|
||||
## Environment
|
||||
|
||||
<a id="s3.1-stdout-vs-stderr"></a>
|
||||
|
||||
### STDOUT vs STDERR
|
||||
|
||||
All error messages should go to `STDERR`.
|
||||
|
@ -114,9 +182,12 @@ if ! do_something; then
|
|||
fi
|
||||
```
|
||||
|
||||
<a id="s4-comments"></a>
|
||||
|
||||
## Comments
|
||||
|
||||
<a id="s4.1-file-header"></a>
|
||||
|
||||
### File Header
|
||||
|
||||
Start each file with a description of its contents.
|
||||
|
@ -135,6 +206,8 @@ Example:
|
|||
```
|
||||
|
||||
|
||||
<a id="s4.2-function-comments"></a>
|
||||
|
||||
### Function Comments
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
out of the ordinary, put a short comment in.
|
||||
|
||||
<a id="s4.4-todo-comments"></a>
|
||||
|
||||
### TODO Comments
|
||||
|
||||
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 ####)
|
||||
```
|
||||
|
||||
<a id="s5-formatting"></a>
|
||||
|
||||
## Formatting
|
||||
|
||||
While you should follow the style that's already there for files that
|
||||
you're modifying, the following are required for any new code.
|
||||
|
||||
<a id="s5.1-indentation"></a>
|
||||
|
||||
### Indentation
|
||||
|
||||
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
|
||||
faithful to the existing indentation.
|
||||
|
||||
<a id="s5.2-line-length-and-long-strings"></a>
|
||||
|
||||
### Line Length and Long Strings
|
||||
|
||||
Maximum line length is 80 characters.
|
||||
|
@ -263,6 +345,8 @@ long_string="I am an exceptionally
|
|||
long string."
|
||||
```
|
||||
|
||||
<a id="s5.3-pipelines"></a>
|
||||
|
||||
### Pipelines
|
||||
|
||||
Pipelines should be split one per line if they don't all fit on one
|
||||
|
@ -286,6 +370,8 @@ command1 \
|
|||
| command4
|
||||
```
|
||||
|
||||
<a id="s5.4-loops"></a>
|
||||
|
||||
### Loops
|
||||
|
||||
Put `; do` and `; then` on the same line as the
|
||||
|
@ -320,6 +406,8 @@ for dir in "${dirs_to_cleanup[@]}"; do
|
|||
done
|
||||
```
|
||||
|
||||
<a id="s5.5-case-statement"></a>
|
||||
|
||||
### Case statement
|
||||
|
||||
* Indent alternatives by 2 spaces.
|
||||
|
@ -374,6 +462,8 @@ while getopts 'abf:v' flag; do
|
|||
done
|
||||
```
|
||||
|
||||
<a id="s5.6-variable-expansion"></a>
|
||||
|
||||
### Variable expansion
|
||||
|
||||
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
|
||||
be used *as well*.
|
||||
|
||||
<a id="s5.7-quoting"></a>
|
||||
|
||||
### Quoting
|
||||
|
||||
* 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 "$#, $@")
|
||||
```
|
||||
|
||||
<a id="s6-features-and-bugs"></a>
|
||||
|
||||
## Features and Bugs
|
||||
|
||||
<a id="s6.1-shelllint"></a>
|
||||
|
||||
<a id="s6.1-shellcheck"></a>
|
||||
|
||||
### ShellCheck
|
||||
|
||||
The [ShellCheck project](https://www.shellcheck.net/) identifies common bugs and
|
||||
warnings for your shell scripts. It is recommended for all scripts, large or
|
||||
small.
|
||||
|
||||
<a id="s6.2-command-substitution"></a>
|
||||
|
||||
### Command Substitution
|
||||
|
||||
Use `$(command)` instead of backticks.
|
||||
|
@ -544,6 +644,8 @@ var="$(command "$(command1)")"
|
|||
var="`command \`command1\``"
|
||||
```
|
||||
|
||||
<a id="s6.3-tests"></a>
|
||||
|
||||
<a id="tests"></a>
|
||||
### Test, `[ … ]`, and `[[ … ]]`
|
||||
|
||||
|
@ -578,6 +680,8 @@ fi
|
|||
|
||||
For the gory details, see E14 at http://tiswww.case.edu/php/chet/bash/FAQ
|
||||
|
||||
<a id="s6.4-testing-strings"></a>
|
||||
|
||||
### Testing Strings
|
||||
|
||||
Use quotes rather than filler characters where possible.
|
||||
|
@ -664,6 +768,8 @@ if [[ "${my_var}" > 3 ]]; then
|
|||
fi
|
||||
```
|
||||
|
||||
<a id="s6.5-wildcard-expansion-of-filenames"></a>
|
||||
|
||||
### 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'
|
||||
```
|
||||
|
||||
<a id="s6.6-eval"></a>
|
||||
|
||||
### Eval
|
||||
|
||||
`eval` should be avoided.
|
||||
|
@ -707,6 +815,8 @@ eval $(set_my_variables)
|
|||
variable="$(eval some_function)"
|
||||
```
|
||||
|
||||
<a id="s6.7-arrays"></a>
|
||||
|
||||
### Arrays
|
||||
|
||||
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)
|
||||
```
|
||||
|
||||
<a id="s6.7.1-arrays-pros"></a>
|
||||
|
||||
#### Arrays Pros
|
||||
|
||||
* 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
|
||||
arbitrary strings, including strings containing whitespace.
|
||||
|
||||
<a id="s6.7.2-arrays-cons"></a>
|
||||
|
||||
#### Arrays Cons
|
||||
|
||||
Using arrays can risk a script’s complexity growing.
|
||||
|
||||
<a id="s6.7.3-arrays-decision"></a>
|
||||
|
||||
#### Arrays Decision
|
||||
|
||||
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
|
||||
avoided altogether; see [above](#when-to-use-shell).
|
||||
|
||||
<a id="s6.8-pipes-to-while"></a>
|
||||
|
||||
### Pipes 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
|
||||
```
|
||||
|
||||
<a id="s6.9-arithmetic"></a>
|
||||
|
||||
### Arithmetic
|
||||
|
||||
Always use `(( … ))` or `$(( … ))` rather than
|
||||
|
@ -915,9 +1035,12 @@ sec=30
|
|||
echo $(( hr * 3600 + min * 60 + sec )) # prints 7530 as expected
|
||||
```
|
||||
|
||||
<a id="s7-naming-conventions"></a>
|
||||
|
||||
## Naming Conventions
|
||||
|
||||
<a id="s7.1-function-names"></a>
|
||||
|
||||
### Function Names
|
||||
|
||||
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
|
||||
functions.
|
||||
|
||||
<a id="s7.2-variable-names"></a>
|
||||
|
||||
### Variable Names
|
||||
|
||||
As for function names.
|
||||
|
@ -960,6 +1085,8 @@ for zone in "${zones[@]}"; do
|
|||
done
|
||||
```
|
||||
|
||||
<a id="s7.3-constants-and-environment-variable-names"></a>
|
||||
|
||||
### Constants and Environment Variable Names
|
||||
|
||||
All caps, separated with underscores, declared at the top of the file.
|
||||
|
@ -991,6 +1118,8 @@ done
|
|||
readonly VERBOSE
|
||||
```
|
||||
|
||||
<a id="s7.4-source-filenames"></a>
|
||||
|
||||
### Source Filenames
|
||||
|
||||
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
|
||||
`make-template`.
|
||||
|
||||
<a id="s7.5-read-only-variables"></a>
|
||||
|
||||
### Read-only Variables
|
||||
|
||||
Use `readonly` or `declare -r` to ensure they're
|
||||
|
@ -1017,6 +1148,8 @@ else
|
|||
fi
|
||||
```
|
||||
|
||||
<a id="s7.6-use-local-variables"></a>
|
||||
|
||||
### Use Local Variables
|
||||
|
||||
Declare function-specific variables with `local`. Declaration
|
||||
|
@ -1056,6 +1189,8 @@ my_func2() {
|
|||
}
|
||||
```
|
||||
|
||||
<a id="s7.7-function-location"></a>
|
||||
|
||||
### Function Location
|
||||
|
||||
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
|
||||
difficult to follow and results in nasty surprises when debugging.
|
||||
|
||||
<a id="s7.8-main"></a>
|
||||
|
||||
### main
|
||||
|
||||
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,
|
||||
`main` is overkill and so is not required.
|
||||
|
||||
<a id="s8-calling-commands"></a>
|
||||
|
||||
## Calling Commands
|
||||
|
||||
<a id="s8.1-checking-return-values"></a>
|
||||
|
||||
### Checking Return Values
|
||||
|
||||
Always check return values and give informative return values.
|
||||
|
@ -1143,6 +1283,8 @@ if (( return_codes[1] != 0 )); then
|
|||
fi
|
||||
```
|
||||
|
||||
<a id="s8.2-builtin-commands-vs-external-commands"></a>
|
||||
|
||||
### Builtin Commands vs. External Commands
|
||||
|
||||
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/')"
|
||||
```
|
||||
|
||||
<a id="s9-conclusion"></a>
|
||||
|
||||
## Conclusion
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user