From ee75979b5d94ae18f930ff91e5b2d51cd554b60d Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Mon, 9 Mar 2026 22:45:54 +0200 Subject: Update content for html --- gemfeed/2025-09-14-bash-golf-part-4.html | 301 +++++++++++++++---------------- 1 file changed, 148 insertions(+), 153 deletions(-) (limited to 'gemfeed/2025-09-14-bash-golf-part-4.html') diff --git a/gemfeed/2025-09-14-bash-golf-part-4.html b/gemfeed/2025-09-14-bash-golf-part-4.html index b0b5459c..457b15d8 100644 --- a/gemfeed/2025-09-14-bash-golf-part-4.html +++ b/gemfeed/2025-09-14-bash-golf-part-4.html @@ -2,17 +2,12 @@ - Bash Golf Part 4 -
-
-
-

Home | Markdown | Gemini

@@ -75,9 +70,9 @@ somecommand \ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
printf 'a\nb\n' \
-    | tee >(sed 's/.*/X:&/; s/$/ :c1/') >(tr a-z A-Z | sed 's/$/ :c2/') \
-    | sed 's/$/ :c3/'
+
printf 'a\nb\n' \
+    | tee >(sed 's/.*/X:&/; s/$/ :c1/') >(tr a-z A-Z | sed 's/$/ :c2/') \
+    | sed 's/$/ :c3/'
 

Output:
@@ -99,8 +94,8 @@ X:b :c1 :c3 by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
/bin/sh -c 'echo hi | tee >(cat)'
-# /bin/sh: 1: Syntax error: "(" unexpected
+
/bin/sh -c 'echo hi | tee >(cat)'
+# /bin/sh: 1: Syntax error: "(" unexpected
 

Combine with set -o pipefail if failures in side branches should fail the whole pipeline.
@@ -111,9 +106,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
set -o pipefail
-printf 'ok\n' | tee >(false) | cat >/dev/null
-echo $?   # 1 because a side branch failed
+
set -o pipefail
+printf 'ok\n' | tee >(false) | cat >/dev/null
+echo $?   # 1 because a side branch failed
 

Further reading:
@@ -128,19 +123,19 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
ssh "$SSH_USER@$SSH_HOST" <<EOF
-    # Go to the work directory
-    cd "$WORK_DIR"
-  
-    # Make a git pull
-    git pull
-  
-    # Export environment variables required for the service to run
-    export AUTH_TOKEN="$APP_AUTH_TOKEN"
-  
-    # Start the service
-    docker compose up -d --build
-EOF
+
ssh "$SSH_USER@$SSH_HOST" <<EOF
+    # Go to the work directory
+    cd "$WORK_DIR"
+  
+    # Make a git pull
+    git pull
+  
+    # Export environment variables required for the service to run
+    export AUTH_TOKEN="$APP_AUTH_TOKEN"
+  
+    # Start the service
+    docker compose up -d --build
+EOF
 

Tips:
@@ -153,10 +148,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
FOO=bar
-cat <<'EOF'
-$FOO is not expanded here
-EOF
+
FOO=bar
+cat <<'EOF'
+$FOO is not expanded here
+EOF
 

Prefer explicit quoting for variables (as above) to avoid surprises. Example (spaces preserved only when quoted):
@@ -165,11 +160,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
WORK_DIR="/tmp/my work"
-ssh host <<EOF
-    cd $WORK_DIR      # may break if unquoted
-    cd "$WORK_DIR"   # safe
-EOF
+
WORK_DIR="/tmp/my work"
+ssh host <<EOF
+    cd $WORK_DIR      # may break if unquoted
+    cd "$WORK_DIR"   # safe
+EOF
 

Consider set -euo pipefail at the top of the remote block for stricter error handling. Example:
@@ -178,11 +173,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
ssh host <<'EOF'
-    set -euo pipefail
-    false   # causes immediate failure
-    echo never
-EOF
+
ssh host <<'EOF'
+    set -euo pipefail
+    false   # causes immediate failure
+    echo never
+EOF
 

Indent-friendly variant: use a dash to strip leading tabs in the body:
@@ -191,10 +186,10 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
cat <<-EOF > script.sh
-	#!/usr/bin/env bash
-	echo "tab-indented content is dedented"
-EOF
+
cat <<-EOF > script.sh
+	#!/usr/bin/env bash
+	echo "tab-indented content is dedented"
+EOF
 

Further reading:
@@ -209,23 +204,23 @@ 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
-set -euo pipefail
+
#!/usr/bin/env bash
+set -euo pipefail
 
-super() {
-    local -r fn=${FUNCNAME[1]}
-    # Split name on :: and dispatch to base implementation
-    local -a parts=( ${fn//::/ } )
-    "${parts[0]}::base::${parts[2]}" "$@"
-}
+super() {
+    local -r fn=${FUNCNAME[1]}
+    # Split name on :: and dispatch to base implementation
+    local -a parts=( ${fn//::/ } )
+    "${parts[0]}::base::${parts[2]}" "$@"
+}
 
-foo::base::greet() { echo "base: $@"; }
-foo::german::greet()  { super "Guten Tag, $@!"; }
-foo::english::greet() { super "Good day,  $@!"; }
+foo::base::greet() { echo "base: $@"; }
+foo::german::greet()  { super "Guten Tag, $@!"; }
+foo::english::greet() { super "Good day,  $@!"; }
 
-for lang in german english; do
-    foo::$lang::greet Paul
-done
+for lang in german english; do
+    foo::$lang::greet Paul
+done
 

Output:
@@ -243,11 +238,11 @@ base: Good day, Paul! by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
user_name=paul
-declare -n ref=user_name
-echo "$ref"       # paul
-ref=julia
-echo "$user_name" # julia
+
user_name=paul
+declare -n ref=user_name
+echo "$ref"       # paul
+ref=julia
+echo "$user_name" # julia
 

Output:
@@ -265,20 +260,20 @@ julia by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
make_var() {
-    local idx=$1; shift
-    local name="slot_$idx"
-    printf -v "$name" '%s' "$*"   # create variable slot_$idx
-}
+
make_var() {
+    local idx=$1; shift
+    local name="slot_$idx"
+    printf -v "$name" '%s' "$*"   # create variable slot_$idx
+}
 
-get_var() {
-    local idx=$1
-    local -n ref="slot_$idx"      # bind ref to slot_$idx
-    printf '%s\n' "$ref"
-}
+get_var() {
+    local idx=$1
+    local -n ref="slot_$idx"      # bind ref to slot_$idx
+    printf '%s\n' "$ref"
+}
 
-make_var 7 "seven"
-get_var 7
+make_var 7 "seven"
+get_var 7
 

Output:
@@ -295,9 +290,9 @@ seven by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
foo() { echo foo; }
-function foo { echo foo; }
-function foo() { echo foo; }
+
foo() { echo foo; }
+function foo { echo foo; }
+function foo() { echo foo; }
 

Recommendation: prefer name() { ... } for portability and consistency.
@@ -310,14 +305,14 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
deploy_check() { test -f deploy.yaml; }
-smoke_test()   { curl -fsS http://localhost/healthz >/dev/null; }
+
deploy_check() { test -f deploy.yaml; }
+smoke_test()   { curl -fsS http://localhost/healthz >/dev/null; }
 
-if deploy_check || smoke_test; then
-    echo "All good."
-else
-    echo "Something failed." >&2
-fi
+if deploy_check || smoke_test; then
+    echo "All good."
+else
+    echo "Something failed." >&2
+fi
 

You can also compress it golf-style:
@@ -326,7 +321,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
deploy_check || smoke_test && echo ok || echo fail >&2
+
deploy_check || smoke_test && echo ok || echo fail >&2
 

Grep, sed, awk quickies


@@ -337,14 +332,14 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
cat > /tmp/ctx.txt <<EOF
-one
-foo
-two
-three
-bar
-EOF
-grep -C1 foo /tmp/ctx.txt
+
cat > /tmp/ctx.txt <<EOF
+one
+foo
+two
+three
+bar
+EOF
+grep -C1 foo /tmp/ctx.txt
 

Output:
@@ -361,10 +356,10 @@ two by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
mkdir -p /tmp/golf/foo /tmp/golf/src
-printf 'bar\n' > /tmp/golf/src/a.txt
-printf 'bar\n' > /tmp/golf/foo/skip.txt
-grep -R --exclude-dir=foo 'bar' /tmp/golf
+
mkdir -p /tmp/golf/foo /tmp/golf/src
+printf 'bar\n' > /tmp/golf/src/a.txt
+printf 'bar\n' > /tmp/golf/foo/skip.txt
+grep -R --exclude-dir=foo 'bar' /tmp/golf
 

Output:
@@ -379,8 +374,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
printf 'A\nB\nC\n' > /tmp/s.txt
-sed -e '1iHEAD' -e '3iMID' /tmp/s.txt
+
printf 'A\nB\nC\n' > /tmp/s.txt
+sed -e '1iHEAD' -e '3iMID' /tmp/s.txt
 

Output:
@@ -399,10 +394,10 @@ C by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
printf 'a b c\nx y z\n' > /tmp/t.txt
-cat /tmp/t.txt
-echo
-awk 'NF{NF-=1};1' /tmp/t.txt
+
printf 'a b c\nx y z\n' > /tmp/t.txt
+cat /tmp/t.txt
+echo
+awk 'NF{NF-=1};1' /tmp/t.txt
 

Output:
@@ -423,7 +418,7 @@ x y by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
find . -type f -name '*.log' -print0 | xargs -0 rm -f
+
find . -type f -name '*.log' -print0 | xargs -0 rm -f
 

Example with spaces and NULs only:
@@ -432,7 +427,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
printf 'a\0b c\0' | xargs -0 -I{} printf '<%s>\n' {}
+
printf 'a\0b c\0' | xargs -0 -I{} printf '<%s>\n' {}
 

Output:
@@ -450,7 +445,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
cfg=$(<config.ini)
+
cfg=$(<config.ini)
 

Read lines into an array safely with mapfile (aka readarray):
@@ -459,8 +454,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
mapfile -t lines < <(grep -v '^#' config.ini)
-printf '%s\n' "${lines[@]}"
+
mapfile -t lines < <(grep -v '^#' config.ini)
+printf '%s\n' "${lines[@]}"
 

Assign formatted strings without a subshell using printf -v:
@@ -469,8 +464,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
printf -v msg 'Hello %s, id=%04d' "$USER" 42
-echo "$msg"
+
printf -v msg 'Hello %s, id=%04d' "$USER" 42
+echo "$msg"
 

Output:
@@ -485,8 +480,8 @@ Hello paul, id=0042 by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
mapfile -d '' -t files < <(find . -type f -print0)
-printf '%s\n' "${files[@]}"
+
mapfile -d '' -t files < <(find . -type f -print0)
+printf '%s\n' "${files[@]}"
 

Quick password generator


@@ -497,7 +492,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
LC_ALL=C tr -dc 'A-Za-z0-9_' </dev/urandom | head -c 16; echo
+
LC_ALL=C tr -dc 'A-Za-z0-9_' </dev/urandom | head -c 16; echo
 

Alternative using openssl:
@@ -506,7 +501,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
openssl rand -base64 16 | tr -d '\n' | cut -c1-22
+
openssl rand -base64 16 | tr -d '\n' | cut -c1-22
 

yes for automation


@@ -517,9 +512,9 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
yes | rm -r large_directory        # auto-confirm
-yes n | dangerous-command          # auto-decline
-yes anything | head -n1            # prints one line: anything
+
yes | rm -r large_directory        # auto-confirm
+yes n | dangerous-command          # auto-decline
+yes anything | head -n1            # prints one line: anything
 

Forcing true to fail (and vice versa)


@@ -530,15 +525,15 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
true()  { return 1; }
-false() { return 0; }
+
true()  { return 1; }
+false() { return 0; }
 
-true  || echo 'true failed'
-false && echo 'false succeeded'
+true  || echo 'true failed'
+false && echo 'false succeeded'
 
-# Bypass function with builtin/command
-builtin true # returns 0
-command true # returns 0
+# Bypass function with builtin/command
+builtin true # returns 0
+command true # returns 0
 

To disable a builtin entirely: enable -n true (re-enable with enable true).
@@ -566,11 +561,11 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
rbash -c 'cd /'            # cd: restricted
-rbash -c 'PATH=/tmp'       # PATH: restricted
-rbash -c 'echo hi > out'   # redirection: restricted
-rbash -c '/bin/echo hi'    # commands with /: restricted
-rbash -c 'exec ls'         # exec: restricted
+
rbash -c 'cd /'            # cd: restricted
+rbash -c 'PATH=/tmp'       # PATH: restricted
+rbash -c 'echo hi > out'   # redirection: restricted
+rbash -c '/bin/echo hi'    # commands with /: restricted
+rbash -c 'exec ls'         # exec: restricted
 

Useless use of cat (and when it’s ok)


@@ -581,12 +576,12 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
# Prefer
-grep -i foo file
-<file grep -i foo        # or feed via redirection
+
# Prefer
+grep -i foo file
+<file grep -i foo        # or feed via redirection
 
-# Over
-cat file | grep -i foo
+# Over
+cat file | grep -i foo
 

But for interactive composition, or when you truly need to concatenate multiple sources into a single stream, cat is fine, as you may think, "First I need the content, then I do X." Changing the "useless use of cat" in retrospect is really a waste of time for one-time interactive use:
@@ -595,7 +590,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
cat file1 file2 | grep -i foo
+
cat file1 file2 | grep -i foo
 

From notes: “Good for interactivity; Useless use of cat” — use judgment.
@@ -608,15 +603,15 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
lockdir=/tmp/myjob.lock
-if mkdir "$lockdir" 2>/dev/null; then
-    trap 'rmdir "$lockdir"' EXIT INT TERM
-    # critical section
-    do_work
-else
-    echo "Another instance is running" >&2
-    exit 1
-fi
+
lockdir=/tmp/myjob.lock
+if mkdir "$lockdir" 2>/dev/null; then
+    trap 'rmdir "$lockdir"' EXIT INT TERM
+    # critical section
+    do_work
+else
+    echo "Another instance is running" >&2
+    exit 1
+fi
 

This works well on Linux. Remove the lock in trap so crashes don’t leave stale locks.
@@ -631,7 +626,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
find . -name '*.log' -exec gzip -9 {} +
+
find . -name '*.log' -exec gzip -9 {} +
 

Example for extglob (exclude two dirs from listing):
@@ -640,8 +635,8 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
shopt -s extglob
-ls -d -- !(.git|node_modules) 2>/dev/null
+
shopt -s extglob
+ls -d -- !(.git|node_modules) 2>/dev/null
 

E-Mail your comments to paul@nospam.buetow.org :-)
@@ -657,11 +652,11 @@ http://www.gnu.org/software/src-highlite -->
Back to the main site
-- cgit v1.2.3