Master Clean Shell Scripts: Proven Practices for Readable, Efficient Bash Code

This article compiles essential shell‑script guidelines—shebang usage, commenting, parameter validation, variable handling, indentation, naming conventions, encoding, permissions, logging, security, line continuation, quoting, modular main functions, scope control, return values, indirect references, heredocs, path resolution, brevity, parallel execution, and search tricks—to help you write maintainable and performant Bash scripts.

MaGe Linux Operations
MaGe Linux Operations
MaGe Linux Operations
Master Clean Shell Scripts: Proven Practices for Readable, Efficient Bash Code

Because of work requirements I recently revisited shell scripting. Although I use most commands daily, my scripts often look messy and are hard to read, especially when compared with others' scripts. Shell scripts are more like toolchains than formal programming languages, so many people write them ad‑hoc, resulting in long, unstructured code.

After consulting various documents I gathered scattered advice into a concise technical specification for my future scripts.

Shebang

The shebang ("#!") on the first line specifies the interpreter when none is given. Common examples: #!/bin/bash You can list supported interpreters with:

$ cat /etc/shells
/bin/sh
/bin/dash
/bin/bash
/rbash
/usr/bin/screen

Running ./a.sh without a shebang uses $SHELL. A portable shebang is recommended: #!/usr/bin/env bash Code Comments

Comments are crucial in shell scripts to explain purpose, parameters, usage, warnings, author info, and function details.

shebang
脚本的参数
脚本的用途
脚本的注意事项
脚本的写作时间,作者,版权等
各个函数前的说明注释
一些较复杂的单行命令注释

Parameter Validation

Always check that arguments meet expectations and provide clear feedback:

if [[ $# != 2 ]]; then
    echo "Parameter incorrect."
    exit 1
fi

Variables and Magic Numbers

Define important environment variables at the top and avoid hard‑coded magic numbers. Example for Java version control:

source /etc/profile
export PATH="/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/apps/bin/"

Use variables instead of literals so changes are easy.

Indentation Rules

Consistent indentation (soft tabs with 2 or 4 spaces, or hard tabs) improves readability, especially in functions and control structures.

Soft tab: n spaces (commonly 2 or 4)

Hard tab: literal "\t" character

Naming Conventions

Follow these standards:

File names end with .sh Variable names are meaningful and correctly spelled

Use lowercase with underscores for identifiers

Encoding

Write scripts in UTF‑8 without BOM. Use English for comments and logs to avoid encoding issues on different machines. When editing on Windows, ensure the file is saved as UTF‑8 without BOM.

Permissions

Remember to make scripts executable (e.g., chmod +x script.sh).

Logging and Echo

Logging aids debugging; real‑time echo helps users track progress. ANSI/VT100 sequences can add colors or effects.

Never Hard‑Code Passwords

Never embed passwords in scripts, especially when the code is stored in public repositories.

Line Continuation

Break long commands with a backslash and a preceding space:

./configure \
    --prefix=/usr \
    --sbin-path=/usr/sbin/nginx \
    --conf-path=/etc/nginx/nginx.conf
Note the space before the backslash.

Efficiency Matters

Choose commands that minimize work. Example: sed -n '1p;1q' file reads only the first line, unlike sed -n '1p' file.

Always Quote Variables

Wrap variable expansions in double quotes to prevent word splitting and globbing:

#!/bin/sh
var="*.sh"
echo $var   # expands to file list
echo "$var" # prints literal *.sh

Use a Main Function

Structure scripts with functions and a main entry point for clarity:

#!/usr/bin/env bash
func1() { :; }
func2() { :; }
main() {
    func1
    func2
}
main "$@"

Scope Considerations

Variables are global by default. Prefer local readonly or declare inside functions to limit scope.

Function Return Values

Functions return integer status codes (0 for success). To return strings, echo the value and capture it:

func() { echo "2333"; }
res=$(func)
echo "This is from $res."

Indirect Variable Reference

Use ${!VAR} to retrieve the value of a variable whose name is stored in another variable.

VAR1="value"
VAR2="VAR1"
echo ${!VAR2}   # prints "value"

Heredocs

Heredocs simplify creating multi‑line files:

cat >> /etc/rsyncd.conf <<EOF
log file = /usr/local/logs/rsyncd.log
transfer logging = yes
log format = %t %a %m %f %b
syslog facility = local3
EOF

Finding Script Directory

Use reliable methods to obtain the script’s own path:

script_dir=$(cd $(dirname $0) && pwd)
# or
script_dir=$(dirname $(readlink -f $0))

Keep Code Short

Prefer a single command over pipelines when possible, e.g., grep root /etc/passwd instead of cat /etc/passwd | grep root. Combining multiple sed expressions into one command also improves speed.

Command Parallelization

Run functions in background and wait for them, or use xargs -P for parallel execution:

for ((i=0;i<10;i++)); do
    func &
 done
wait

Full‑Text Search

When searching files, handle spaces in filenames and binary files correctly:

find . -type f -name '*.txt' -print0 | xargs -0 grep -a 2333

Adopt New Syntax

Define functions as func(){} instead of func{} Use [[ ]] for tests

Prefer $(...) over backticks for command substitution

Use printf instead of echo for complex output

Other Tips

Prefer absolute paths; if using relative paths, prefix with ./ Prefer Bash parameter expansion over awk / sed for simple tasks

Write simple if statements on one line using && and || Namespace exported variables to avoid collisions

Use trap to handle termination signals

Create temporary files with mktemp Redirect unwanted output to /dev/null Check command exit status to detect failures

Test file existence before operating on it

Avoid parsing ls output

Read files with while read loops instead of for When copying directories, ensure the destination exists or use cp -r appropriately

Source: https://blog.mythsman.com/post/5d2ab67ff678ba2eb3bd346f/

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Linuxcode styleBash
MaGe Linux Operations
Written by

MaGe Linux Operations

Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.