From d2be28ca4b86021518caddac606e553a54dd8927 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Mon, 23 Jun 2025 07:55:27 +0300 Subject: Update content for html --- ...021-05-16-personal-bash-coding-style-guide.html | 276 ++++++++++----------- 1 file changed, 138 insertions(+), 138 deletions(-) (limited to 'gemfeed/2021-05-16-personal-bash-coding-style-guide.html') diff --git a/gemfeed/2021-05-16-personal-bash-coding-style-guide.html b/gemfeed/2021-05-16-personal-bash-coding-style-guide.html index 75c528c3..f34a8170 100644 --- a/gemfeed/2021-05-16-personal-bash-coding-style-guide.html +++ b/gemfeed/2021-05-16-personal-bash-coding-style-guide.html @@ -66,7 +66,7 @@ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
#!/bin/bash 
+
#!/bin/bash 
 

... as the shebang line, but that does not work on all Unix and Unix-like operating systems (e.g., the *BSDs don't have Bash installed to /bin/bash). Better is:
@@ -75,7 +75,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
#!/usr/bin/env bash
+
#!/usr/bin/env bash
 

Two space soft-tabs indentation


@@ -96,14 +96,14 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
# All fits on one line
-command1 | command2
+
# All fits on one line
+command1 | command2
 
-# Long commands
-command1 \
-  | command2 \
-  | command3 \
-  | command4
+# Long commands
+command1 \
+  | command2 \
+  | command3 \
+  | command4
 

I think there is a better way like the following, which is less noisy. The pipe | already indicates the Bash that another command is expected, thus making the explicit line breaks with \ obsolete:
@@ -112,11 +112,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
# Long commands
-command1 |
-    command2 |
-    command3 |
-    command4
+
# Long commands
+command1 |
+    command2 |
+    command3 |
+    command4
 

Update: It's 2023 now, and I have changed my mind. I think Google's way is the better one. It may be a bit more to type, but the leading | are a nice eye catcher, so you know immediately what is going on!
@@ -129,11 +129,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
greet () {
-    local -r greeting="${1}"
-    local -r name="${2}"
-    echo "${greeting} ${name}!"
-}
+
greet () {
+    local -r greeting="${1}"
+    local -r name="${2}"
+    echo "${greeting} ${name}!"
+}
 

In this particular example, I agree that you should quote them as you don't know the input (are there, for example, whitespace characters?). But if you are sure that you are only using simple bare words, then I think that the code looks much cleaner when you do this instead:
@@ -142,11 +142,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
say_hello_to_paul () {
-    local -r greeting=Hello
-    local -r name=Paul
-    echo "$greeting $name!"
-}
+
say_hello_to_paul () {
+    local -r greeting=Hello
+    local -r name=Paul
+    echo "$greeting $name!"
+}
 

You see, I also omitted the curly braces { } around the variables. I only use the curly braces around variables when it makes the code either easier/clearer to read or if it is necessary to use them:
@@ -155,9 +155,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
declare FOO=bar
-# Curly braces around FOO are necessary
-echo "foo${FOO}baz"
+
declare FOO=bar
+# Curly braces around FOO are necessary
+echo "foo${FOO}baz"
 

A few more words on always quoting the variables: For the sake of consistency (and for making ShellCheck happy), I am not against quoting everything I encounter. I also think that the larger the Bash script becomes, the more critical it becomes always to quote variables. That's because it will be more likely that you might not remember that some of the functions don't work on values with spaces in them, for example. It's just that I won't quote everything in every small script I write.
@@ -170,13 +170,13 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
# Prefer this:
-addition=$(( X + Y ))
-substitution="${string/#foo/bar}"
+
# Prefer this:
+addition=$(( X + Y ))
+substitution="${string/#foo/bar}"
 
-# Instead of this:
-addition="$(expr "${X}" + "${Y}")"
-substitution="$(echo "${string}" | sed -e 's/^foo/bar/')"
+# Instead of this:
+addition="$(expr "${X}" + "${Y}")"
+substitution="$(echo "${string}" | sed -e 's/^foo/bar/')"
 

I can't entirely agree here. The external commands (especially sed) are much more sophisticated and powerful than the built-in Bash versions. Sed can do much more than the Bash can ever do by itself when it comes to text manipulation (the name "sed" stands for streaming editor, after all).
@@ -197,20 +197,20 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
declare -r SUGAR_FREE=yes
-declare -r I_NEED_THE_BUZZ=no
+
declare -r SUGAR_FREE=yes
+declare -r I_NEED_THE_BUZZ=no
 
-buy_soda () {
-    local -r sugar_free=$1
+buy_soda () {
+    local -r sugar_free=$1
 
-    if [[ $sugar_free == yes ]]; then
-        echo 'Diet Dr. Pepper'
-    else
-        echo 'Pepsi Coke'
-    fi
-}
+    if [[ $sugar_free == yes ]]; then
+        echo 'Diet Dr. Pepper'
+    else
+        echo 'Pepsi Coke'
+    fi
+}
 
-buy_soda $I_NEED_THE_BUZZ
+buy_soda $I_NEED_THE_BUZZ
 

Non-evil alternative to variable assignments via eval


@@ -221,12 +221,12 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
# What does this set?
-# Did it succeed? In part or whole?
-eval $(set_my_variables)
+
# 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)"
+# What happens if one of the returned values has a space in it?
+variable="$(eval some_function)"
 

However, if I want to read variables from another file, I don't have to use eval here. I only have to source the file:
@@ -265,39 +265,39 @@ Hello paul, it is Sat 15 May 19:21:12 BST 2021 by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
filter_lines () {
-    echo 'Start filtering lines in a fancy way!' >&2
-    grep ... | sed ....
-}
+
filter_lines () {
+    echo 'Start filtering lines in a fancy way!' >&2
+    grep ... | sed ....
+}
 
-process_lines () {
-    echo 'Start processing line by line!' >&2
-    while read -r line; do
-        ... do something and produce a result...
-        echo "$result"
-    done 
-}
+process_lines () {
+    echo 'Start processing line by line!' >&2
+    while read -r line; do
+        ... do something and produce a result...
+        echo "$result"
+    done 
+}
 
-# Do some post-processing of the data
-postprocess_lines () {
-    echo 'Start removing duplicates!' >&2
-    sort -u
-}
+# Do some post-processing of the data
+postprocess_lines () {
+    echo 'Start removing duplicates!' >&2
+    sort -u
+}
 
-genreate_report () {
-    echo 'My boss wants to have a report!' >&2
-    tee outfile.txt
-    wc -l outfile.txt
-}
+genreate_report () {
+    echo 'My boss wants to have a report!' >&2
+    tee outfile.txt
+    wc -l outfile.txt
+}
 
-main () {
-    filter_lines |
-        process_lines |
-        postprocess_lines |
-        generate_report
-}
+main () {
+    filter_lines |
+        process_lines |
+        postprocess_lines |
+        generate_report
+}
 
-main
+main
 

The stdout is always passed as a pipe to the next following stage. The stderr is used for info logging.
@@ -312,13 +312,13 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
some_function () {
-    local -r param_foo="$1"; shift
-    local -r param_baz="$1"; shift
-    local -r param_bay="$1"; shift
+
some_function () {
+    local -r param_foo="$1"; shift
+    local -r param_baz="$1"; shift
+    local -r param_bay="$1"; shift
 
-    # ...
-}
+    # ...
+}
 

Want to add a param_baz? Just do this:
@@ -327,14 +327,14 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
some_function () {
-    local -r param_foo="$1"; shift
-    local -r param_bar="$1"; shift
-    local -r param_baz="$1"; shift
-    local -r param_bay="$1"; shift
+
some_function () {
+    local -r param_foo="$1"; shift
+    local -r param_bar="$1"; shift
+    local -r param_baz="$1"; shift
+    local -r param_bay="$1"; shift
 
-    # ...
-}
+    # ...
+}
 

Want to remove param_foo? Nothing easier than that:
@@ -343,13 +343,13 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
some_function () {
-    local -r param_bar="$1"; shift
-    local -r param_baz="$1"; shift
-    local -r param_bay="$1"; shift
-    
-    # ...
-}
+
some_function () {
+    local -r param_bar="$1"; shift
+    local -r param_baz="$1"; shift
+    local -r param_bay="$1"; shift
+    
+    # ...
+}
 

As you can see, I didn't need to change any other assignments within the function. Of course, you would also need to change the function argument lists at every occasion where the function is invoked - you would do that within the same refactoring session.
@@ -362,9 +362,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
set -e
-grep -q foo <<< bar
-echo Jo
+
set -e
+grep -q foo <<< bar
+echo Jo
 

Here 'Jo' will never be printed out as the grep didn't find any match. It's unrealistic for most scripts to run in paranoid mode purely, so there must be a way to add exceptions. Critical Bash scripts of mine tend to look like this:
@@ -373,26 +373,26 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
#!/usr/bin/env bash
+
#!/usr/bin/env bash
 
-set -e
+set -e
 
-some_function () {
-    # .. some critical code
-    # ...
+some_function () {
+    # .. some critical code
+    # ...
 
-    set +e
-    # Grep might fail, but that's OK now
-    grep ....
-    local -i ec=$?
-    set -e
+    set +e
+    # Grep might fail, but that's OK now
+    grep ....
+    local -i ec=$?
+    set -e
 
-    # .. critical code continues ...
-    if [[ $ec -ne 0 ]]; then
-        : # ...
-    fi
-    # ...
-}
+    # .. critical code continues ...
+    if [[ $ec -ne 0 ]]; then
+        : # ...
+    fi
+    # ...
+}
 

Learned


@@ -407,10 +407,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
if [[ "${my_var}" > 3 ]]; then
-    # True for 4, false for 22.
-    do_something
-fi
+
if [[ "${my_var}" > 3 ]]; then
+    # True for 4, false for 22.
+    do_something
+fi
 

... but it is probably an unintended lexicographical comparison. A correct way would be:
@@ -419,9 +419,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
if (( my_var > 3 )); then
-    do_something
-fi
+
if (( my_var > 3 )); then
+    do_something
+fi
 

or
@@ -430,9 +430,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
if [[ "${my_var}" -gt 3 ]]; then
-    do_something
-fi
+
if [[ "${my_var}" -gt 3 ]]; then
+    do_something
+fi
 

PIPESTATUS


@@ -445,10 +445,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
tar -cf - ./* | ( cd "${dir}" && tar -xf - )
-if (( PIPESTATUS[0] != 0 || PIPESTATUS[1] != 0 )); then
-    echo "Unable to tar files to ${dir}" >&2
-fi
+
tar -cf - ./* | ( cd "${dir}" && tar -xf - )
+if (( PIPESTATUS[0] != 0 || PIPESTATUS[1] != 0 )); then
+    echo "Unable to tar files to ${dir}" >&2
+fi
 

However, as PIPESTATUS 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 PIPESTATUS to another variable immediately after running the command (don't forget that [ is a command and will wipe out PIPESTATUS).
@@ -457,14 +457,14 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
tar -cf - ./* | ( cd "${DIR}" && tar -xf - )
-return_codes=( "${PIPESTATUS[@]}" )
-if (( return_codes[0] != 0 )); then
-    do_something
-fi
-if (( return_codes[1] != 0 )); then
-    do_something_else
-fi
+
tar -cf - ./* | ( cd "${DIR}" && tar -xf - )
+return_codes=( "${PIPESTATUS[@]}" )
+if (( return_codes[0] != 0 )); then
+    do_something
+fi
+if (( return_codes[1] != 0 )); then
+    do_something_else
+fi
 

Use common sense and BE CONSISTENT.


-- cgit v1.2.3