1282 lines
62 KiB
HTML
1282 lines
62 KiB
HTML
<html><head><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><title>Shell Style Guide</title><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><link rel="shortcut icon" type="image/x-icon" href="https://www.google.com/favicon.ico"><link rel="stylesheet" type="text/css" href="Shell%20Style%20Guide_files/styleguide.css"><script type="text/javascript" language="javascript">
|
|
|
|
function GetElementsByName(name) {
|
|
// Workaround a bug on old versions of opera.
|
|
if (document.getElementsByName) {
|
|
return document.getElementsByName(name);
|
|
} else {
|
|
return [document.getElementById(name)];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {string} namePrefix The prefix of the body name.
|
|
* @param {function(boolean): boolean} getVisibility Computes the new
|
|
* visibility state, given the current one.
|
|
*/
|
|
function ChangeVisibility(namePrefix, getVisibility) {
|
|
var bodyName = namePrefix + '__body';
|
|
var buttonName = namePrefix + '__button';
|
|
var bodyElements = GetElementsByName(bodyName);
|
|
var linkElement = GetElementsByName('link-' + buttonName)[0];
|
|
if (bodyElements.length != 1) {
|
|
throw Error('ShowHideByName() got the wrong number of bodyElements: ' +
|
|
bodyElements.length);
|
|
} else {
|
|
var bodyElement = bodyElements[0];
|
|
var buttonElement = GetElementsByName(buttonName)[0];
|
|
var isVisible = bodyElement.style.display != "none";
|
|
if (getVisibility(isVisible)) {
|
|
bodyElement.style.display = "inline";
|
|
linkElement.style.display = "block";
|
|
buttonElement.innerHTML = '▽';
|
|
} else {
|
|
bodyElement.style.display = "none";
|
|
linkElement.style.display = "none";
|
|
buttonElement.innerHTML = '▶';
|
|
}
|
|
}
|
|
}
|
|
|
|
function ShowHideByName(namePrefix) {
|
|
ChangeVisibility(namePrefix, function(old) { return !old; });
|
|
}
|
|
|
|
function ShowByName(namePrefix) {
|
|
ChangeVisibility(namePrefix, function() { return true; });
|
|
}
|
|
|
|
function ShowHideAll() {
|
|
var allButton = GetElementsByName("show_hide_all_button")[0];
|
|
if (allButton.innerHTML == '▽') {
|
|
allButton.innerHTML = '▶';
|
|
SetHiddenState(document.getElementsByTagName("body")[0].childNodes, "none", '▶');
|
|
} else {
|
|
allButton.innerHTML = '▽';
|
|
SetHiddenState(document.getElementsByTagName("body")[0].childNodes, "inline", '▽');
|
|
}
|
|
}
|
|
|
|
// Recursively sets state of all children
|
|
// of a particular node.
|
|
function SetHiddenState(root, newState, newButton) {
|
|
for (var i = 0; i != root.length; i++) {
|
|
SetHiddenState(root[i].childNodes, newState, newButton);
|
|
if (root[i].className == 'showhide_button') {
|
|
root[i].innerHTML = newButton;
|
|
}
|
|
if (root[i].className == 'stylepoint_body' ||
|
|
root[i].className == 'link_button') {
|
|
root[i].style.display = newState;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
function EndsWith(str, suffix) {
|
|
var l = str.length - suffix.length;
|
|
return l >= 0 && str.indexOf(suffix, l) == l;
|
|
}
|
|
|
|
function RefreshVisibilityFromHashParam() {
|
|
var hashRegexp = new RegExp('#([^&#]*)$');
|
|
var hashMatch = hashRegexp.exec(window.location.href);
|
|
var anchor = hashMatch && GetElementsByName(hashMatch[1])[0];
|
|
var node = anchor;
|
|
var suffix = '__body';
|
|
while (node) {
|
|
var id = node.id;
|
|
var matched = id && EndsWith(id, suffix);
|
|
if (matched) {
|
|
var len = id.length - suffix.length;
|
|
ShowByName(id.substring(0, len));
|
|
if (anchor.scrollIntoView) {
|
|
anchor.scrollIntoView();
|
|
}
|
|
|
|
return;
|
|
}
|
|
node = node.parentNode;
|
|
}
|
|
}
|
|
|
|
window.onhashchange = RefreshVisibilityFromHashParam;
|
|
|
|
window.onload = function() {
|
|
// if the URL contains "?showall=y", expand the details of all children
|
|
var showHideAllRegex = new RegExp("[\\?&](showall)=([^&#]*)");
|
|
var showHideAllValue = showHideAllRegex.exec(window.location.href);
|
|
if (showHideAllValue != null) {
|
|
if (showHideAllValue[2] == "y") {
|
|
SetHiddenState(document.getElementsByTagName("body")[0].childNodes,
|
|
"inline", '▽');
|
|
} else {
|
|
SetHiddenState(document.getElementsByTagName("body")[0].childNodes,
|
|
"none", '▶');
|
|
}
|
|
}
|
|
var showOneRegex = new RegExp("[\\?&](showone)=([^&#]*)");
|
|
var showOneValue = showOneRegex.exec(window.location.href);
|
|
if (showOneValue) {
|
|
ShowHideByName(showOneValue[2]);
|
|
}
|
|
|
|
|
|
RefreshVisibilityFromHashParam();
|
|
}
|
|
</script></head><body><h1>Shell Style Guide</h1>
|
|
|
|
<p align="right">
|
|
|
|
Revision 1.26
|
|
</p>
|
|
|
|
|
|
<address>
|
|
Paul Armstrong<br>
|
|
Too many more to mention<br>
|
|
</address>
|
|
|
|
<div style="margin-left: 50%; font-size: 75%;"><p>
|
|
Each style point has a summary for which additional information is available
|
|
by toggling the accompanying arrow button that looks this way:
|
|
<span style="margin-left: 0; float: none" class="showhide_button">▶</span>.
|
|
You may toggle all summaries with the big arrow button:
|
|
</p><div style=" font-size: larger; margin-left: +2em;"><span id="show_hide_all_button" name="show_hide_all_button" onclick="javascript:ShowHideAll()" style="font-size: 180%; float: none" class="showhide_button">▶</span>
|
|
Toggle all summaries
|
|
</div></div><div class="toc"><div class="toc_title">Table of Contents</div><table><tbody><tr class="" valign="top"><td><div class="toc_category"><a href="#Shell_Files_and_Interpreter_Invocation">Shell Files and Interpreter Invocation</a></div></td><td><div class="toc_stylepoint"><span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#File_Extensions">File Extensions</a></span> <span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#SUID/SGID">SUID/SGID</a></span> </div></td></tr><tr class="" valign="top"><td><div class="toc_category"><a href="#Environment">Environment</a></div></td><td><div class="toc_stylepoint"><span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#STDOUT_vs_STDERR">STDOUT vs STDERR</a></span> </div></td></tr><tr class="" valign="top"><td><div class="toc_category"><a href="#Comments">Comments</a></div></td><td><div class="toc_stylepoint"><span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#File_Header">File Header</a></span> <span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#Function_Comments">Function Comments</a></span> <span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#Implementation_Comments">Implementation Comments</a></span> <span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#TODO_Comments">TODO Comments</a></span> </div></td></tr><tr class="" valign="top"><td><div class="toc_category"><a href="#Formatting">Formatting</a></div></td><td><div class="toc_stylepoint"><span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#Indentation">Indentation</a></span> <span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#Line_Length_and_Long_Strings">Line Length and Long Strings</a></span> <span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#Pipelines">Pipelines</a></span> <span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#Loops">Loops</a></span> <span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#Case_statement">Case statement</a></span> <span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#Variable_expansion">Variable expansion</a></span> <span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#Quoting">Quoting</a></span> </div></td></tr><tr class="" valign="top"><td><div class="toc_category"><a href="#Features_and_Bugs">Features and Bugs</a></div></td><td><div class="toc_stylepoint"><span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#Command_Substitution">Command Substitution</a></span> <span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#Test,_[_and_[[">Test, [ and [[</a></span> <span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#Testing_Strings">Testing Strings</a></span> <span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#Wildcard_Expansion_of_Filenames">Wildcard Expansion of Filenames</a></span> <span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#Eval">Eval</a></span> <span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#Pipes_to_While">Pipes to While</a></span> </div></td></tr><tr class="" valign="top"><td><div class="toc_category"><a href="#Naming_Conventions">Naming Conventions</a></div></td><td><div class="toc_stylepoint"><span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#Function_Names">Function Names</a></span> <span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#Variable_Names">Variable Names</a></span> <span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#Constants_and_Environment_Variable_Names">Constants and Environment Variable Names</a></span> <span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#Source_Filenames">Source Filenames</a></span> <span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#Read-only_Variables">Read-only Variables</a></span> <span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#Use_Local_Variables">Use Local Variables</a></span> <span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#Function_Location">Function Location</a></span> <span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#main">main</a></span> </div></td></tr><tr class="" valign="top"><td><div class="toc_category"><a href="#Calling_Commands">Calling Commands</a></div></td><td><div class="toc_stylepoint"><span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#Checking_Return_Values">Checking Return Values</a></span> <span class="" style="padding-right: 1em; white-space:nowrap;"><a href="#Builtin_Commands_vs._External_Commands">Builtin Commands vs. External Commands</a></span> </div></td></tr><tr class="" valign="top"><td><div class="toc_category"><a href="#Conclusion">Conclusion</a></div></td><td><div class="toc_stylepoint"></div></td></tr></tbody></table></div>
|
|
|
|
<div class=""><h2 id="Background" name="Background">Background</h2>
|
|
|
|
|
|
|
|
<div class=""><h3><a id="Which_Shell_to_Use" name="Which_Shell_to_Use">Which Shell to Use</a></h3><span name="link-Which_Shell_to_Use__button" id="link-Which_Shell_to_Use__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Which_Shell_to_Use#Which_Shell_to_Use">
|
|
link
|
|
</a></span><span id="Which_Shell_to_Use__button" name="Which_Shell_to_Use__button" onclick="javascript:ShowHideByName('Which_Shell_to_Use')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
<code>Bash</code> is the only shell scripting language permitted for
|
|
executables.
|
|
</div>
|
|
<div class=""><div style="display: none" id="Which_Shell_to_Use__body" name="Which_Shell_to_Use__body" class="stylepoint_body">
|
|
<p>
|
|
Executables must start with <code>#!/bin/bash</code> and a minimum
|
|
number of flags. Use <code>set</code> to set shell options so that
|
|
calling your script as <code>bash <i><script_name></i></code>
|
|
does not break its functionality.
|
|
</p>
|
|
<p>
|
|
Restricting all executable shell scripts to bash
|
|
gives us a consistent shell language that's installed on all our
|
|
machines.
|
|
</p>
|
|
<p>
|
|
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.
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
<div class=""><h3><a id="When_to_use_Shell" name="When_to_use_Shell">When to use Shell</a></h3><span name="link-When_to_use_Shell__button" id="link-When_to_use_Shell__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=When_to_use_Shell#When_to_use_Shell">
|
|
link
|
|
</a></span><span id="When_to_use_Shell__button" name="When_to_use_Shell__button" onclick="javascript:ShowHideByName('When_to_use_Shell')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
Shell should only be used for small utilities or simple wrapper
|
|
scripts.
|
|
</div>
|
|
<div class=""><div style="display: none" id="When_to_use_Shell__body" name="When_to_use_Shell__body" class="stylepoint_body">
|
|
<p>
|
|
While shell scripting isn't a development language, it is used for
|
|
writing various utility scripts throughout Google. This
|
|
style guide is more a recognition of its use rather than
|
|
a suggestion that it be used for widespread deployment.
|
|
</p>
|
|
<p>
|
|
Some guidelines:
|
|
<ul>
|
|
<li>
|
|
If you're mostly calling other utilities and are doing relatively
|
|
little data manipulation, shell is an acceptable choice for the
|
|
task.
|
|
</li>
|
|
<li>
|
|
If performance matters, use something other than shell.
|
|
</li>
|
|
<li>
|
|
If you find you need to use arrays for anything more than
|
|
assignment of <code>${PIPESTATUS}</code>, you should use Python.
|
|
</li>
|
|
<li>
|
|
If you are writing a script that is more than 100 lines long, you
|
|
should probably be writing it in Python instead. Bear in mind
|
|
that scripts grow. Rewrite your script in another language
|
|
early to avoid a time-consuming rewrite at a later date.
|
|
</li>
|
|
</ul>
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<div class=""><h2 id="Shell_Files_and_Interpreter_Invocation" name="Shell_Files_and_Interpreter_Invocation">Shell Files and Interpreter Invocation</h2>
|
|
|
|
<div class=""><h3><a id="File_Extensions" name="File_Extensions">File Extensions</a></h3><span style="display: none;" name="link-File_Extensions__button" id="link-File_Extensions__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=File_Extensions#File_Extensions">
|
|
link
|
|
</a></span><span id="File_Extensions__button" name="File_Extensions__button" onclick="javascript:ShowHideByName('File_Extensions')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
Executables should have no extension (strongly preferred) or a
|
|
<code>.sh</code> extension.
|
|
Libraries must have a <code>.sh</code> extension and should not be
|
|
executable.
|
|
</div>
|
|
<div class=""><div style="display: none;" id="File_Extensions__body" name="File_Extensions__body" class="stylepoint_body">
|
|
<p>
|
|
It is not necessary to know what language a program is written in when
|
|
executing it and shell doesn't require an extension so we prefer not to
|
|
use one for executables.
|
|
</p>
|
|
<p>
|
|
However, for libraries it's important to know what language it is and
|
|
sometimes there's a need to have similar libraries in different
|
|
languages. This allows library files with identical purposes but
|
|
different languages to be identically named except for the
|
|
language-specific suffix.
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
<div class=""><h3><a id="SUID/SGID" name="SUID/SGID">SUID/SGID</a></h3><span name="link-SUID/SGID__button" id="link-SUID/SGID__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=SUID/SGID#SUID/SGID">
|
|
link
|
|
</a></span><span id="SUID/SGID__button" name="SUID/SGID__button" onclick="javascript:ShowHideByName('SUID/SGID')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
SUID and SGID are <em>forbidden</em> on shell scripts.
|
|
</div>
|
|
<div class=""><div style="display: none" id="SUID/SGID__body" name="SUID/SGID__body" class="stylepoint_body">
|
|
<p>
|
|
There are too many security issues with shell that make it nearly
|
|
impossible to secure sufficiently to allow SUID/SGID. While bash does
|
|
make it difficult to run SUID, it's still possible on some platforms
|
|
which is why we're being explicit about banning it.
|
|
</p>
|
|
<p>
|
|
Use <code>sudo</code> to provide elevated access if you need it.
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class=""><h2 id="Environment" name="Environment">Environment</h2>
|
|
|
|
<div class=""><h3><a id="STDOUT_vs_STDERR" name="STDOUT_vs_STDERR">STDOUT vs STDERR</a></h3><span name="link-STDOUT_vs_STDERR__button" id="link-STDOUT_vs_STDERR__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=STDOUT_vs_STDERR#STDOUT_vs_STDERR">
|
|
link
|
|
</a></span><span id="STDOUT_vs_STDERR__button" name="STDOUT_vs_STDERR__button" onclick="javascript:ShowHideByName('STDOUT_vs_STDERR')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
All error messages should go to <code>STDERR</code>.
|
|
</div>
|
|
<div class=""><div style="display: none" id="STDOUT_vs_STDERR__body" name="STDOUT_vs_STDERR__body" class="stylepoint_body">
|
|
<p>
|
|
This makes it easier
|
|
to separate normal status from actual issues.
|
|
</p>
|
|
<p>
|
|
A function to print out error messages along with other status
|
|
information is recommended.
|
|
<div class=""><pre>err() {
|
|
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $@" >&2
|
|
}
|
|
|
|
if ! do_something; then
|
|
err "Unable to do_something"
|
|
exit "${E_DID_NOTHING}"
|
|
fi</pre></div>
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class=""><h2 id="Comments" name="Comments">Comments</h2>
|
|
|
|
<div class=""><h3><a id="File_Header" name="File_Header">File Header</a></h3><span name="link-File_Header__button" id="link-File_Header__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=File_Header#File_Header">
|
|
link
|
|
</a></span><span id="File_Header__button" name="File_Header__button" onclick="javascript:ShowHideByName('File_Header')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
Start each file with a description of its contents.
|
|
</div>
|
|
<div class=""><div style="display: none" id="File_Header__body" name="File_Header__body" class="stylepoint_body">
|
|
<p>
|
|
Every file must have a top-level comment including a brief overview of
|
|
its contents.
|
|
A
|
|
copyright notice
|
|
and author information are optional.
|
|
</p>
|
|
<p>
|
|
Example:
|
|
<div class=""><pre>#!/bin/bash
|
|
#
|
|
# Perform hot backups of Oracle databases.</pre></div>
|
|
</p>
|
|
|
|
|
|
</div></div>
|
|
</div>
|
|
|
|
<div class=""><h3><a id="Function_Comments" name="Function_Comments">Function Comments</a></h3><span name="link-Function_Comments__button" id="link-Function_Comments__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Function_Comments#Function_Comments">
|
|
link
|
|
</a></span><span id="Function_Comments__button" name="Function_Comments__button" onclick="javascript:ShowHideByName('Function_Comments')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
Any function that is not both obvious and short must be commented. Any
|
|
function in a library must be commented regardless of length or
|
|
complexity.
|
|
</div>
|
|
<div class=""><div style="display: none" id="Function_Comments__body" name="Function_Comments__body" class="stylepoint_body">
|
|
<p>
|
|
It should be possible for someone else to learn how to use your
|
|
program or to use a function in your library by reading the comments
|
|
(and self-help, if provided) without reading the code.
|
|
</p>
|
|
<p>
|
|
All function comments should contain:
|
|
<ul>
|
|
<li>
|
|
Description of the function
|
|
</li>
|
|
<li>
|
|
Global variables used and modified
|
|
</li>
|
|
<li>
|
|
Arguments taken
|
|
</li>
|
|
<li>
|
|
Returned values other than the default exit status of the last
|
|
command run
|
|
</li>
|
|
</ul>
|
|
</p>
|
|
<p>
|
|
Example:
|
|
<div class=""><pre>#!/bin/bash
|
|
#
|
|
# Perform hot backups of Oracle databases.
|
|
|
|
export PATH='/usr/xpg4/bin:/usr/bin:/opt/csw/bin:/opt/goog/bin'
|
|
|
|
#######################################
|
|
# Cleanup files from the backup dir
|
|
# Globals:
|
|
# BACKUP_DIR
|
|
# ORACLE_SID
|
|
# Arguments:
|
|
# None
|
|
# Returns:
|
|
# None
|
|
#######################################
|
|
cleanup() {
|
|
...
|
|
}</pre></div>
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
<div class=""><h3><a id="Implementation_Comments" name="Implementation_Comments">Implementation Comments</a></h3><span name="link-Implementation_Comments__button" id="link-Implementation_Comments__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Implementation_Comments#Implementation_Comments">
|
|
link
|
|
</a></span><span id="Implementation_Comments__button" name="Implementation_Comments__button" onclick="javascript:ShowHideByName('Implementation_Comments')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
Comment tricky, non-obvious, interesting or important parts of your code.
|
|
</div>
|
|
<div class=""><div style="display: none" id="Implementation_Comments__body" name="Implementation_Comments__body" class="stylepoint_body">
|
|
<p>
|
|
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.
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
<div class=""><h3><a id="TODO_Comments" name="TODO_Comments">TODO Comments</a></h3><span name="link-TODO_Comments__button" id="link-TODO_Comments__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=TODO_Comments#TODO_Comments">
|
|
link
|
|
</a></span><span id="TODO_Comments__button" name="TODO_Comments__button" onclick="javascript:ShowHideByName('TODO_Comments')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
Use TODO comments for code that is temporary, a short-term solution, or
|
|
good-enough but not perfect.
|
|
</div>
|
|
<div class=""><div style="display: none" id="TODO_Comments__body" name="TODO_Comments__body" class="stylepoint_body">
|
|
<p>
|
|
This matches the convention in the <a href="https://google.github.io/styleguide/cppguide.xml?showone=TODO_Comments#TODO_Comments">C++
|
|
Guide</a>.
|
|
</p>
|
|
<p>
|
|
TODOs should include the string TODO in all caps, followed by your
|
|
username in parentheses. A colon is optional. It's preferable to put a
|
|
bug/ticket number next to the TODO item as well.
|
|
</p>
|
|
<p>
|
|
Examples:
|
|
|
|
<div class=""><pre># TODO(mrmonkey): Handle the unlikely edge cases (bug ####)</pre></div>
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class=""><h2 id="Formatting" name="Formatting">Formatting</h2>
|
|
<p>
|
|
While you should follow the style that's already there for files that
|
|
you're modifying, the following are required for any new code.
|
|
</p>
|
|
|
|
<div class=""><h3><a id="Indentation" name="Indentation">Indentation</a></h3><span name="link-Indentation__button" id="link-Indentation__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Indentation#Indentation">
|
|
link
|
|
</a></span><span id="Indentation__button" name="Indentation__button" onclick="javascript:ShowHideByName('Indentation')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
Indent 2 spaces. No tabs.
|
|
</div>
|
|
<div class=""><div style="display: none" id="Indentation__body" name="Indentation__body" class="stylepoint_body">
|
|
<p>
|
|
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.
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
<div class=""><h3><a id="Line_Length_and_Long_Strings" name="Line_Length_and_Long_Strings">Line Length and Long Strings</a></h3><span style="display: none;" name="link-Line_Length_and_Long_Strings__button" id="link-Line_Length_and_Long_Strings__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Line_Length_and_Long_Strings#Line_Length_and_Long_Strings">
|
|
link
|
|
</a></span><span id="Line_Length_and_Long_Strings__button" name="Line_Length_and_Long_Strings__button" onclick="javascript:ShowHideByName('Line_Length_and_Long_Strings')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
Maximum line length is 80 characters.
|
|
</div>
|
|
<div class=""><div style="display: none;" id="Line_Length_and_Long_Strings__body" name="Line_Length_and_Long_Strings__body" class="stylepoint_body">
|
|
<p>
|
|
If you have to write strings that are longer than 80 characters, this
|
|
should be done with a here document or an embedded newline if possible.
|
|
Literal strings that have to be longer than 80 chars and can't sensibly
|
|
be split are ok, but it's strongly preferred to find a way to make it
|
|
shorter.
|
|
</p>
|
|
<p>
|
|
<div class=""><pre># DO use 'here document's
|
|
cat <<END;
|
|
I am an exceptionally long
|
|
string.
|
|
END
|
|
|
|
# Embedded newlines are ok too
|
|
long_string="I am an exceptionally
|
|
long string."</pre></div>
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
<div class=""><h3><a id="Pipelines" name="Pipelines">Pipelines</a></h3><span style="display: none;" name="link-Pipelines__button" id="link-Pipelines__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Pipelines#Pipelines">
|
|
link
|
|
</a></span><span id="Pipelines__button" name="Pipelines__button" onclick="javascript:ShowHideByName('Pipelines')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
Pipelines should be split one per line if they don't all fit on one line.
|
|
</div>
|
|
<div class=""><div style="display: none;" id="Pipelines__body" name="Pipelines__body" class="stylepoint_body">
|
|
<p>
|
|
If a pipeline all fits on one line, it should be on one line.
|
|
</p>
|
|
<p>
|
|
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 '&&'.
|
|
<div class=""><pre># All fits on one line
|
|
command1 | command2
|
|
|
|
# Long commands
|
|
command1 \
|
|
| command2 \
|
|
| command3 \
|
|
| command4</pre></div>
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
<div class=""><h3><a id="Loops" name="Loops">Loops</a></h3><span name="link-Loops__button" id="link-Loops__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Loops#Loops">
|
|
link
|
|
</a></span><span id="Loops__button" name="Loops__button" onclick="javascript:ShowHideByName('Loops')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
Put <code>; do</code> and <code>; then</code> on the same line as the
|
|
<code>while</code>, <code>for</code> or <code>if</code>.
|
|
</div>
|
|
<div class=""><div style="display: none" id="Loops__body" name="Loops__body" class="stylepoint_body">
|
|
<p>
|
|
Loops in shell are a bit different, but we follow the same principles
|
|
as with braces when declaring functions. That is: <code>; then</code>
|
|
and <code>; do</code> should be on the same line as the if/for/while.
|
|
<code>else</code> should be on its own line and closing statements
|
|
should be on their own line vertically aligned with the opening
|
|
statement.
|
|
</p>
|
|
<p>
|
|
Example:
|
|
<div class=""><pre>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</pre></div>
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
<div class=""><h3><a id="Case_statement" name="Case_statement">Case statement</a></h3><span name="link-Case_statement__button" id="link-Case_statement__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Case_statement#Case_statement">
|
|
link
|
|
</a></span><span id="Case_statement__button" name="Case_statement__button" onclick="javascript:ShowHideByName('Case_statement')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
<ul>
|
|
<li>
|
|
Indent alternatives by 2 spaces.
|
|
</li>
|
|
<li>
|
|
A one-line alternative needs a space after the close parenthesis of
|
|
the pattern and before the <code>;;</code>.
|
|
</li>
|
|
<li>
|
|
Long or multi-command alternatives should be split over multiple
|
|
lines with the pattern, actions, and <code>;;</code> on separate
|
|
lines.
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class=""><div style="display: none" id="Case_statement__body" name="Case_statement__body" class="stylepoint_body">
|
|
<p>
|
|
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
|
|
<code>;&</code> and <code>;;&</code> notations.
|
|
</p>
|
|
<div class=""><pre>case "${expression}" in
|
|
a)
|
|
variable="..."
|
|
some_command "${variable}" "${other_expr}" ...
|
|
;;
|
|
absolute)
|
|
actions="relative"
|
|
another_command "${actions}" "${other_expr}" ...
|
|
;;
|
|
*)
|
|
error "Unexpected expression '${expression}'"
|
|
;;
|
|
esac</pre></div>
|
|
<p>
|
|
Simple commands may be put on the same line as the pattern <i>and</i>
|
|
<code>;;</code> as long as the expression remains readable. This is
|
|
often appropriate for single-letter option processing. When the
|
|
actions don't fit on a single line, put the pattern on a line on its
|
|
own, then the actions, then <code>;;</code> also on a line of its own.
|
|
When on the same line as the actions, use a space after the close
|
|
parenthesis of the pattern and another before the <code>;;</code>.
|
|
</p>
|
|
<div class=""><pre>verbose='false'
|
|
aflag=''
|
|
bflag=''
|
|
files=''
|
|
while getopts 'abf:v' flag; do
|
|
case "${flag}" in
|
|
a) aflag='true' ;;
|
|
b) bflag='true' ;;
|
|
f) files="${OPTARG}" ;;
|
|
v) verbose='true' ;;
|
|
*) error "Unexpected option ${flag}" ;;
|
|
esac
|
|
done</pre></div>
|
|
</div></div>
|
|
</div>
|
|
|
|
<div class=""><h3><a id="Variable_expansion" name="Variable_expansion">Variable expansion</a></h3><span name="link-Variable_expansion__button" id="link-Variable_expansion__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Variable_expansion#Variable_expansion">
|
|
link
|
|
</a></span><span id="Variable_expansion__button" name="Variable_expansion__button" onclick="javascript:ShowHideByName('Variable_expansion')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
In order of precedence: Stay consistent with what you find;
|
|
quote your variables;
|
|
prefer "${var}" over "$var", but see details.
|
|
</div>
|
|
<div class=""><div style="display: none" id="Variable_expansion__body" name="Variable_expansion__body" class="stylepoint_body">
|
|
<p>
|
|
These are meant to be guidelines, as the topic seems too controversial for
|
|
a mandatory regulation.
|
|
<br>
|
|
They are listed in order of precedence.
|
|
</p>
|
|
<ol>
|
|
<li>
|
|
Stay consistent with what you find for existing code.
|
|
</li>
|
|
<li>
|
|
Quote variables, see <a href="#Quoting">Quoting section below</a>.
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Don't brace-quote single character shell
|
|
specials / positional parameters, unless strictly necessary
|
|
or avoiding deep confusion.
|
|
<br>
|
|
Prefer brace-quoting all other variables.
|
|
<div class=""><pre># Section of recommended cases.
|
|
|
|
# Preferred style for 'special' variables:
|
|
echo "Positional: $1" "$5" "$3"
|
|
echo "Specials: !=$!, -=$-, _=$_. ?=$?, #=$# *=$* @=$@ \$=$$ ..."
|
|
|
|
# Braces necessary:
|
|
echo "many parameters: ${10}"
|
|
|
|
# Braces avoiding confusion:
|
|
# Output is "a0b0c0"
|
|
set -- a b c
|
|
echo "${1}0${2}0${3}0"
|
|
|
|
# Preferred style for other variables:
|
|
echo "PATH=${PATH}, PWD=${PWD}, mine=${some_var}"
|
|
while read f; do
|
|
echo "file=${f}"
|
|
done < <(ls -l /tmp)
|
|
|
|
# Section of discouraged cases
|
|
|
|
# Unquoted vars, unbraced vars, brace-quoted single letter
|
|
# shell specials.
|
|
echo a=$avar "b=$bvar" "PID=${$}" "${1}"
|
|
|
|
# Confusing use: this is expanded as "${1}0${2}0${3}0",
|
|
# not "${10}${20}${30}
|
|
set -- a b c
|
|
echo "$10$20$30"</pre></div>
|
|
</p>
|
|
</li>
|
|
</ol>
|
|
</div></div>
|
|
</div>
|
|
|
|
<div class=""><h3><a id="Quoting" name="Quoting">Quoting</a></h3><span name="link-Quoting__button" id="link-Quoting__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Quoting#Quoting">
|
|
link
|
|
</a></span><span id="Quoting__button" name="Quoting__button" onclick="javascript:ShowHideByName('Quoting')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
<ul>
|
|
<li>
|
|
Always quote strings containing variables, command substitutions,
|
|
spaces or shell meta characters, unless careful unquoted expansion
|
|
is required.
|
|
</li>
|
|
<li>
|
|
Prefer quoting strings that are "words"
|
|
(as opposed to command options or path names).
|
|
</li>
|
|
<li>
|
|
Never quote <em>literal</em> integers.
|
|
</li>
|
|
<li>
|
|
Be aware of the quoting rules for
|
|
<a href="#Test,_%5B_and_%5B%5B">pattern matches in [[</a>.
|
|
</li>
|
|
<li>
|
|
Use "$@" unless you have a specific reason to use $*.
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class=""><div style="display: none" id="Quoting__body" name="Quoting__body" class="stylepoint_body">
|
|
<p>
|
|
<div class=""><pre># 'Single' quotes indicate that no substitution is desired.
|
|
# "Double" quotes indicate that substitution is required/tolerated.
|
|
|
|
# Simple examples
|
|
# "quote command substitutions"
|
|
flag="$(some_command and its args "$@" 'quoted separately')"
|
|
|
|
# "quote variables"
|
|
echo "${flag}"
|
|
|
|
# "never quote literal integers"
|
|
value=32
|
|
# "quote command substitutions", even when you expect integers
|
|
number="$(generate_number)"
|
|
|
|
# "prefer quoting words", not compulsory
|
|
readonly USE_INTEGER='true'
|
|
|
|
# "quote shell meta characters"
|
|
echo 'Hello stranger, and well met. Earn lots of $$$'
|
|
echo "Process $$: Done making \$\$\$."
|
|
|
|
# "command options or path names"
|
|
# ($1 is assumed to contain a value here)
|
|
grep -li Hugo /dev/null "$1"
|
|
|
|
# Less simple examples
|
|
# "quote variables, unless proven false": ccs might be empty
|
|
git send-email --to "${reviewers}" ${ccs:+"--cc" "${ccs}"}
|
|
|
|
# Positional parameter precautions: $1 might be unset
|
|
# Single quotes leave regex as-is.
|
|
grep -cP '([Ss]pecial|\|?characters*)$' ${1:+"$1"}
|
|
|
|
# For passing on arguments,
|
|
# "$@" is right almost everytime, and
|
|
# $* is wrong almost everytime:
|
|
#
|
|
# * $* and $@ will split on spaces, clobbering up arguments
|
|
# that contain spaces and dropping empty strings;
|
|
# * "$@" will retain arguments as-is, so no args
|
|
# provided will result in no args being passed on;
|
|
# This is in most cases what you want to use for passing
|
|
# on arguments.
|
|
# * "$*" expands to one argument, with all args joined
|
|
# by (usually) spaces,
|
|
# so no args provided will result in one empty string
|
|
# being passed on.
|
|
# (Consult 'man bash' for the nit-grits ;-)
|
|
|
|
set -- 1 "2 two" "3 three tres"; echo $# ; set -- "$*"; echo "$#, $@")
|
|
set -- 1 "2 two" "3 three tres"; echo $# ; set -- "$@"; echo "$#, $@")</pre></div>
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class=""><h2 id="Features_and_Bugs" name="Features_and_Bugs">Features and Bugs</h2>
|
|
|
|
<div class=""><h3><a id="Command_Substitution" name="Command_Substitution">Command Substitution</a></h3><span name="link-Command_Substitution__button" id="link-Command_Substitution__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Command_Substitution#Command_Substitution">
|
|
link
|
|
</a></span><span id="Command_Substitution__button" name="Command_Substitution__button" onclick="javascript:ShowHideByName('Command_Substitution')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
Use <code>$(command)</code> instead of backticks.
|
|
</div>
|
|
<div class=""><div style="display: none" id="Command_Substitution__body" name="Command_Substitution__body" class="stylepoint_body">
|
|
<p>
|
|
Nested backticks require escaping the inner ones with <code>\</code>.
|
|
The <code>$(command)</code> format doesn't change when nested and is
|
|
easier to read.
|
|
</p>
|
|
<p>
|
|
Example:
|
|
<div class=""><pre># This is preferred:
|
|
var="$(command "$(command1)")"
|
|
|
|
# This is not:
|
|
var="`command \`command1\``"</pre></div>
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
<div class=""><h3><a id="Test,_[_and_[[" name="Test,_[_and_[[">Test, [ and [[</a></h3><span name="link-Test,_[_and_[[__button" id="link-Test,_[_and_[[__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Test,_[_and_[[#Test,_[_and_[[">
|
|
link
|
|
</a></span><span id="Test,_[_and_[[__button" name="Test,_[_and_[[__button" onclick="javascript:ShowHideByName('Test,_[_and_[[')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
<code>[[ ... ]]</code> is preferred over <code>[</code>,
|
|
<code>test</code> and <code>/usr/bin/[</code>.
|
|
</div>
|
|
<div class=""><div style="display: none" id="Test,_[_and_[[__body" name="Test,_[_and_[[__body" class="stylepoint_body">
|
|
<p>
|
|
<code>[[ ... ]]</code> reduces errors as no pathname expansion or word
|
|
splitting takes place between <code>[[</code> and <code>]]</code> and
|
|
<code>[[ ... ]]</code> allows for regular expression matching where
|
|
<code>[ ... ]</code> does not.
|
|
<div class=""><pre># 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 https://tiswww.case.edu/php/chet/bash/FAQ
|
|
if [[ "filename" =~ ^[[:alnum:]]+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</pre></div>
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
<div class=""><h3><a id="Testing_Strings" name="Testing_Strings">Testing Strings</a></h3><span name="link-Testing_Strings__button" id="link-Testing_Strings__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Testing_Strings#Testing_Strings">
|
|
link
|
|
</a></span><span id="Testing_Strings__button" name="Testing_Strings__button" onclick="javascript:ShowHideByName('Testing_Strings')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
Use quotes rather than filler characters where possible.
|
|
</div>
|
|
<div class=""><div style="display: none" id="Testing_Strings__body" name="Testing_Strings__body" class="stylepoint_body">
|
|
<p>
|
|
Bash is smart enough to deal with an empty string in a test. So, given
|
|
that the code is much easier to read, use tests for empty/non-empty
|
|
strings or empty strings rather than filler characters.
|
|
<div class=""><pre># Do this:
|
|
if [[ "${my_var}" = "some_string" ]]; then
|
|
do_something
|
|
fi
|
|
|
|
# -z (string length is zero) and -n (string length is not zero) are
|
|
# preferred over testing for an empty string
|
|
if [[ -z "${my_var}" ]]; then
|
|
do_something
|
|
fi
|
|
|
|
# This is OK (ensure quotes on the empty side), but not preferred:
|
|
if [[ "${my_var}" = "" ]]; then
|
|
do_something
|
|
fi
|
|
|
|
# Not this:
|
|
if [[ "${my_var}X" = "some_stringX" ]]; then
|
|
do_something
|
|
fi</pre></div>
|
|
</p>
|
|
<p>
|
|
To avoid confusion about what you're testing for, explicitly use
|
|
<code>-z</code> or <code>-n</code>.
|
|
<div class=""><pre># Use this
|
|
if [[ -n "${my_var}" ]]; then
|
|
do_something
|
|
fi
|
|
|
|
# Instead of this as errors can occur if ${my_var} expands to a test
|
|
# flag
|
|
if [[ "${my_var}" ]]; then
|
|
do_something
|
|
fi</pre></div>
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
<div class=""><h3><a id="Wildcard_Expansion_of_Filenames" name="Wildcard_Expansion_of_Filenames">Wildcard Expansion of Filenames</a></h3><span name="link-Wildcard_Expansion_of_Filenames__button" id="link-Wildcard_Expansion_of_Filenames__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Wildcard_Expansion_of_Filenames#Wildcard_Expansion_of_Filenames">
|
|
link
|
|
</a></span><span id="Wildcard_Expansion_of_Filenames__button" name="Wildcard_Expansion_of_Filenames__button" onclick="javascript:ShowHideByName('Wildcard_Expansion_of_Filenames')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
Use an explicit path when doing wildcard expansion of filenames.
|
|
</div>
|
|
<div class=""><div style="display: none" id="Wildcard_Expansion_of_Filenames__body" name="Wildcard_Expansion_of_Filenames__body" class="stylepoint_body">
|
|
<p>
|
|
As filenames can begin with a <code>-</code>, it's a lot safer to
|
|
expand wildcards with <code>./*</code> instead of <code>*</code>.
|
|
<div class=""><pre># Here's the contents of the directory:
|
|
# -f -r somedir somefile
|
|
|
|
# This deletes almost everything in the directory by force
|
|
psa@bilby$ rm -v *
|
|
removed directory: `somedir'
|
|
removed `somefile'
|
|
|
|
# As opposed to:
|
|
psa@bilby$ rm -v ./*
|
|
removed `./-f'
|
|
removed `./-r'
|
|
rm: cannot remove `./somedir': Is a directory
|
|
removed `./somefile'</pre></div>
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
<div class=""><h3><a id="Eval" name="Eval">Eval</a></h3><span name="link-Eval__button" id="link-Eval__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Eval#Eval">
|
|
link
|
|
</a></span><span id="Eval__button" name="Eval__button" onclick="javascript:ShowHideByName('Eval')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
<code>eval</code> should be avoided.
|
|
</div>
|
|
<div class=""><div style="display: none" id="Eval__body" name="Eval__body" class="stylepoint_body">
|
|
<p>
|
|
Eval munges the input when used for assignment to variables and can set
|
|
variables without making it possible to check what those variables
|
|
were.
|
|
<div class=""><pre># What does this set?
|
|
# Did it succeed? In part or whole?
|
|
eval $(set_my_variables)
|
|
|
|
# What happens if one of the returned values has a space in it?
|
|
variable="$(eval some_function)"</pre></div>
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
<div class=""><h3><a id="Pipes_to_While" name="Pipes_to_While">Pipes to While</a></h3><span style="display: block;" name="link-Pipes_to_While__button" id="link-Pipes_to_While__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Pipes_to_While#Pipes_to_While">
|
|
link
|
|
</a></span><span id="Pipes_to_While__button" name="Pipes_to_While__button" onclick="javascript:ShowHideByName('Pipes_to_While')" class="showhide_button">▽</span>
|
|
<div class="" style="display:inline;">
|
|
Use process substitution or for loops in preference to piping to while.
|
|
Variables modified in a while loop do not propagate to the parent
|
|
because the loop's commands run in a subshell.
|
|
</div>
|
|
<div class=""><div style="display: inline;" id="Pipes_to_While__body" name="Pipes_to_While__body" class="stylepoint_body">
|
|
<p>
|
|
The implicit subshell in a pipe to while can make it difficult to track
|
|
down bugs.
|
|
<div class=""><pre class="badcode">last_line='NULL'
|
|
your_command | while read line; do
|
|
last_line="${line}"
|
|
done
|
|
|
|
# This will output 'NULL'
|
|
echo "${last_line}"</pre></div>
|
|
</p>
|
|
<p>
|
|
Use a for loop if you are confident that the input will not contain
|
|
spaces or special characters (usually, this means not user input).
|
|
<div class=""><pre>total=0
|
|
# Only do this if there are no spaces in return values.
|
|
for value in $(command); do
|
|
total+="${value}"
|
|
done</pre></div>
|
|
</p>
|
|
<p>
|
|
Using process substitution allows redirecting output but puts the
|
|
commands in an explicit subshell rather than the implicit subshell that
|
|
bash creates for the while loop.
|
|
<div class=""><pre>total=0
|
|
last_file=
|
|
while read count filename; do
|
|
total+="${count}"
|
|
last_file="${filename}"
|
|
done < <(your_command | uniq -c)
|
|
|
|
# This will output the second field of the last line of output from
|
|
# the command.
|
|
echo "Total = ${total}"
|
|
echo "Last one = ${last_file}"</pre></div>
|
|
</p>
|
|
<p>
|
|
Use while loops where it is not necessary to pass complex results
|
|
to the parent shell - this is typically where some more complex
|
|
"parsing" is required. Beware that simple examples are probably
|
|
more easily done with a tool such as awk. This may also be useful
|
|
where you specifically don't want to change the parent scope variables.
|
|
<div class=""><pre># Trivial implementation of awk expression:
|
|
# awk '$3 == "nfs" { print $2 " maps to " $1 }' /proc/mounts
|
|
cat /proc/mounts | while read src dest type opts rest; do
|
|
if [[ ${type} == "nfs" ]]; then
|
|
echo "NFS ${dest} maps to ${src}"
|
|
fi
|
|
done</pre></div>
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class=""><h2 id="Naming_Conventions" name="Naming_Conventions">Naming Conventions</h2>
|
|
|
|
<div class=""><h3><a id="Function_Names" name="Function_Names">Function Names</a></h3><span name="link-Function_Names__button" id="link-Function_Names__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Function_Names#Function_Names">
|
|
link
|
|
</a></span><span id="Function_Names__button" name="Function_Names__button" onclick="javascript:ShowHideByName('Function_Names')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
Lower-case, with underscores to separate words. Separate libraries
|
|
with <code>::</code>. Parentheses are required after the function name.
|
|
The keyword <code>function</code> is optional, but must be used
|
|
consistently throughout a project.
|
|
</div>
|
|
<div class=""><div style="display: none" id="Function_Names__body" name="Function_Names__body" class="stylepoint_body">
|
|
<p>
|
|
If you're writing single functions, use lowercase and separate words
|
|
with underscore. If you're writing a package, separate package names
|
|
with <code>::</code>. Braces must be on the same line as the function
|
|
name (as with other languages at Google) and no space between the
|
|
function name and the parenthesis.
|
|
<div class=""><pre># Single function
|
|
my_func() {
|
|
...
|
|
}
|
|
|
|
# Part of a package
|
|
mypackage::my_func() {
|
|
...
|
|
}</pre></div>
|
|
</p>
|
|
<p>
|
|
The <code>function</code> keyword is extraneous when "()" is present
|
|
after the function name, but enhances quick identification of
|
|
functions.
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
<div class=""><h3><a id="Variable_Names" name="Variable_Names">Variable Names</a></h3><span name="link-Variable_Names__button" id="link-Variable_Names__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Variable_Names#Variable_Names">
|
|
link
|
|
</a></span><span id="Variable_Names__button" name="Variable_Names__button" onclick="javascript:ShowHideByName('Variable_Names')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
As for function names.
|
|
</div>
|
|
<div class=""><div style="display: none" id="Variable_Names__body" name="Variable_Names__body" class="stylepoint_body">
|
|
<p>
|
|
Variables names for loops should be similarly named for any variable
|
|
you're looping through.
|
|
<div class=""><pre>for zone in ${zones}; do
|
|
something_with "${zone}"
|
|
done</pre></div>
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
<div class=""><h3><a id="Constants_and_Environment_Variable_Names" name="Constants_and_Environment_Variable_Names">Constants and Environment Variable Names</a></h3><span name="link-Constants_and_Environment_Variable_Names__button" id="link-Constants_and_Environment_Variable_Names__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Constants_and_Environment_Variable_Names#Constants_and_Environment_Variable_Names">
|
|
link
|
|
</a></span><span id="Constants_and_Environment_Variable_Names__button" name="Constants_and_Environment_Variable_Names__button" onclick="javascript:ShowHideByName('Constants_and_Environment_Variable_Names')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
All caps, separated with underscores, declared at the top of the file.
|
|
</div>
|
|
<div class=""><div style="display: none" id="Constants_and_Environment_Variable_Names__body" name="Constants_and_Environment_Variable_Names__body" class="stylepoint_body">
|
|
<p>
|
|
Constants and anything exported to the environment should be
|
|
capitalized.
|
|
<div class=""><pre># Constant
|
|
readonly PATH_TO_FILES='/some/path'
|
|
|
|
# Both constant and environment
|
|
declare -xr ORACLE_SID='PROD'</pre></div>
|
|
</p>
|
|
<p>
|
|
Some things become constant at their first setting (for example, via
|
|
getopts). Thus, it's OK to set a constant in getopts or based on a
|
|
condition, but it should be made readonly immediately afterwards.
|
|
Note that <code>declare</code> doesn't operate on global variables
|
|
within functions, so <code>readonly</code> or <code>export</code> is
|
|
recommended instead.
|
|
</p>
|
|
<div class=""><pre>VERBOSE='false'
|
|
while getopts 'v' flag; do
|
|
case "${flag}" in
|
|
v) VERBOSE='true' ;;
|
|
esac
|
|
done
|
|
readonly VERBOSE</pre></div>
|
|
</div></div>
|
|
</div>
|
|
|
|
<div class=""><h3><a id="Source_Filenames" name="Source_Filenames">Source Filenames</a></h3><span name="link-Source_Filenames__button" id="link-Source_Filenames__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Source_Filenames#Source_Filenames">
|
|
link
|
|
</a></span><span id="Source_Filenames__button" name="Source_Filenames__button" onclick="javascript:ShowHideByName('Source_Filenames')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
Lowercase, with underscores to separate words if desired.
|
|
</div>
|
|
<div class=""><div style="display: none" id="Source_Filenames__body" name="Source_Filenames__body" class="stylepoint_body">
|
|
<p>
|
|
This is for consistency with other code styles in Google:
|
|
<code>maketemplate</code> or <code>make_template</code> but not
|
|
<code>make-template</code>.
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
<div class=""><h3><a id="Read-only_Variables" name="Read-only_Variables">Read-only Variables</a></h3><span name="link-Read-only_Variables__button" id="link-Read-only_Variables__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Read-only_Variables#Read-only_Variables">
|
|
link
|
|
</a></span><span id="Read-only_Variables__button" name="Read-only_Variables__button" onclick="javascript:ShowHideByName('Read-only_Variables')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
Use <code>readonly</code> or <code>declare -r</code> to ensure they're
|
|
read only.
|
|
</div>
|
|
<div class=""><div style="display: none" id="Read-only_Variables__body" name="Read-only_Variables__body" class="stylepoint_body">
|
|
<p>
|
|
As globals are widely used in shell, it's important to catch errors
|
|
when working with them. When you declare a variable that is
|
|
meant to be read-only, make this explicit.
|
|
<div class=""><pre>zip_version="$(dpkg --status zip | grep Version: | cut -d ' ' -f 2)"
|
|
if [[ -z "${zip_version}" ]]; then
|
|
error_message
|
|
else
|
|
readonly zip_version
|
|
fi</pre></div>
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
<div class=""><h3><a id="Use_Local_Variables" name="Use_Local_Variables">Use Local Variables</a></h3><span name="link-Use_Local_Variables__button" id="link-Use_Local_Variables__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Use_Local_Variables#Use_Local_Variables">
|
|
link
|
|
</a></span><span id="Use_Local_Variables__button" name="Use_Local_Variables__button" onclick="javascript:ShowHideByName('Use_Local_Variables')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
Declare function-specific variables with <code>local</code>. Declaration
|
|
and assignment should be on different lines.
|
|
</div>
|
|
<div class=""><div style="display: none" id="Use_Local_Variables__body" name="Use_Local_Variables__body" class="stylepoint_body">
|
|
<p>
|
|
Ensure that local variables are only seen inside a function and its
|
|
children by using <code>local</code> when declaring them. This avoids
|
|
polluting the global name space and inadvertently setting variables
|
|
that may have significance outside the function.
|
|
</p>
|
|
<p>
|
|
Declaration and assignment must be separate statements when
|
|
the assignment value is provided by a command substitution; as
|
|
the 'local' builtin does not propagate the exit code from the
|
|
command substitution.
|
|
<div class=""><pre>my_func2() {
|
|
local name="$1"
|
|
|
|
# Separate lines for declaration and assignment:
|
|
local my_var
|
|
my_var="$(my_func)" || return
|
|
|
|
# DO NOT do this: $? contains the exit code of 'local', not my_func
|
|
local my_var="$(my_func)"
|
|
[[ $? -eq 0 ]] || return
|
|
|
|
...
|
|
}</pre></div>
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
<div class=""><h3><a id="Function_Location" name="Function_Location">Function Location</a></h3><span name="link-Function_Location__button" id="link-Function_Location__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Function_Location#Function_Location">
|
|
link
|
|
</a></span><span id="Function_Location__button" name="Function_Location__button" onclick="javascript:ShowHideByName('Function_Location')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
Put all functions together in the file just below constants. Don't hide
|
|
executable code between functions.
|
|
</div>
|
|
<div class=""><div style="display: none" id="Function_Location__body" name="Function_Location__body" class="stylepoint_body">
|
|
<p>
|
|
If you've got functions, put them all together near the top of the
|
|
file. Only includes, <code>set</code> statements and setting constants
|
|
may be done before declaring functions.
|
|
</p>
|
|
<p>
|
|
Don't hide executable code between functions. Doing so makes the code
|
|
difficult to follow and results in nasty surprises when debugging.
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
<div class=""><h3><a id="main" name="main">main</a></h3><span name="link-main__button" id="link-main__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=main#main">
|
|
link
|
|
</a></span><span id="main__button" name="main__button" onclick="javascript:ShowHideByName('main')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
A function called <code>main</code> is required for scripts long enough
|
|
to contain at least one other function.
|
|
</div>
|
|
<div class=""><div style="display: none" id="main__body" name="main__body" class="stylepoint_body">
|
|
<p>
|
|
In order to easily find the start of the program, put the main
|
|
program in a function called <code>main</code> as the bottom most
|
|
function. This provides consistency with the rest of the code base as
|
|
well as allowing you to define more variables as <code>local</code>
|
|
(which can't be done if the main code is not a function). The last
|
|
non-comment line in the file should be a call to <code>main</code>:
|
|
<div class=""><pre>main "$@"</pre></div>
|
|
</p>
|
|
<p>
|
|
Obviously, for short scripts where it's just a linear flow,
|
|
<code>main</code> is overkill and so is not required.
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class=""><h2 id="Calling_Commands" name="Calling_Commands">Calling Commands</h2>
|
|
|
|
<div class=""><h3><a id="Checking_Return_Values" name="Checking_Return_Values">Checking Return Values</a></h3><span name="link-Checking_Return_Values__button" id="link-Checking_Return_Values__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Checking_Return_Values#Checking_Return_Values">
|
|
link
|
|
</a></span><span id="Checking_Return_Values__button" name="Checking_Return_Values__button" onclick="javascript:ShowHideByName('Checking_Return_Values')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
Always check return values and give informative return values.
|
|
</div>
|
|
<div class=""><div style="display: none" id="Checking_Return_Values__body" name="Checking_Return_Values__body" class="stylepoint_body">
|
|
<p>
|
|
For unpiped commands, use <code>$?</code> or check directly via an
|
|
<code>if</code> statement to keep it simple.
|
|
</p>
|
|
<p>
|
|
Example:
|
|
<div class=""><pre>if ! mv "${file_list}" "${dest_dir}/" ; then
|
|
echo "Unable to move ${file_list} to ${dest_dir}" >&2
|
|
exit "${E_BAD_MOVE}"
|
|
fi
|
|
|
|
# Or
|
|
mv "${file_list}" "${dest_dir}/"
|
|
if [[ "$?" -ne 0 ]]; then
|
|
echo "Unable to move ${file_list} to ${dest_dir}" >&2
|
|
exit "${E_BAD_MOVE}"
|
|
fi</pre></div>
|
|
</p>
|
|
<p>
|
|
Bash also has the <code>PIPESTATUS</code> variable that allows checking
|
|
of the return code from all parts of a pipe. If it's only necessary to
|
|
check success or failure of the whole pipe, then the following is
|
|
acceptable:
|
|
<div class=""><pre>tar -cf - ./* | ( cd "${dir}" && tar -xf - )
|
|
if [[ "${PIPESTATUS[0]}" -ne 0 || "${PIPESTATUS[1]}" -ne 0 ]]; then
|
|
echo "Unable to tar files to ${dir}" >&2
|
|
fi</pre></div>
|
|
</p>
|
|
<p>
|
|
However, as <code>PIPESTATUS</code> will be overwritten as soon as you
|
|
do any other command, if you need to act differently on errors based on
|
|
where it happened in the pipe, you'll need to assign
|
|
<code>PIPESTATUS</code> to another variable immediately after running
|
|
the command (don't forget that <code>[</code> is a command and will
|
|
wipe out <code>PIPESTATUS</code>).
|
|
<div class=""><pre>tar -cf - ./* | ( cd "${DIR}" && tar -xf - )
|
|
return_codes=(${PIPESTATUS[*]})
|
|
if [[ "${return_codes[0]}" -ne 0 ]]; then
|
|
do_something
|
|
fi
|
|
if [[ "${return_codes[1]}" -ne 0 ]]; then
|
|
do_something_else
|
|
fi</pre></div>
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
<div class=""><h3><a id="Builtin_Commands_vs._External_Commands" name="Builtin_Commands_vs._External_Commands">Builtin Commands vs. External Commands</a></h3><span name="link-Builtin_Commands_vs._External_Commands__button" id="link-Builtin_Commands_vs._External_Commands__button" class="link_button"><a href="https://google.github.io/styleguide/shell.xml?showone=Builtin_Commands_vs._External_Commands#Builtin_Commands_vs._External_Commands">
|
|
link
|
|
</a></span><span id="Builtin_Commands_vs._External_Commands__button" name="Builtin_Commands_vs._External_Commands__button" onclick="javascript:ShowHideByName('Builtin_Commands_vs._External_Commands')" class="showhide_button">▶</span>
|
|
<div class="" style="display:inline;">
|
|
Given the choice between invoking a shell builtin and invoking a separate
|
|
process, choose the builtin.
|
|
</div>
|
|
<div class=""><div style="display: none" id="Builtin_Commands_vs._External_Commands__body" name="Builtin_Commands_vs._External_Commands__body" class="stylepoint_body">
|
|
<p>
|
|
We prefer the use of builtins such as the <em>Parameter Expansion</em>
|
|
functions in <code>bash(1)</code> as it's more robust and portable
|
|
(especially when compared to things like sed).
|
|
</p>
|
|
<p>
|
|
Example:
|
|
<div class=""><pre># Prefer this:
|
|
addition=$((${X} + ${Y}))
|
|
substitution="${string/#foo/bar}"
|
|
|
|
# Instead of this:
|
|
addition="$(expr ${X} + ${Y})"
|
|
substitution="$(echo "${string}" | sed -e 's/^foo/bar/')"</pre></div>
|
|
</p>
|
|
</div></div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class=""><h2 id="Conclusion" name="Conclusion">Conclusion</h2>
|
|
<p>
|
|
Use common sense and <em>BE CONSISTENT</em>.
|
|
</p>
|
|
<p>
|
|
Please take a few minutes to read the Parting Words section at the bottom
|
|
of the <a href="https://google.github.io/styleguide/cppguide.xml">C++ Guide</a>.
|
|
</p>
|
|
</div>
|
|
|
|
<p align="right">
|
|
Revision 1.26
|
|
</p>
|
|
|
|
</body></html> |