Unix Shell Scripts   «Prev  Next»

Lesson 1

Basic UNIX Shell Scripts

A UNIX shell script is a text file containing a sequence of commands that the shell interpreter reads and executes in order. Shell scripts are the primary tool for system administration, task automation, and repetitive operations on any UNIX or Linux system. They allow administrators and developers to combine individual UNIX commands into reusable programs that can be scheduled, parameterized, and integrated into larger workflows without writing a compiled application.

This course offers a hands-on introduction to creating shell scripts in the UNIX command line environment. It is the first in a two-part series. No prior shell programming experience is required, but familiarity with basic UNIX concepts is assumed — logging into a system, navigating the filesystem from the command line, and running common UNIX commands. In this course you will build on those concepts to write your own shell programs and apply them immediately in a live UNIX environment.

Shell scripting is practiced today on three primary platforms: Linux distributions including Ubuntu, RHEL, Debian, and Arch Linux; macOS, which uses zsh as its default interactive shell with Bash available via Homebrew; and Windows Subsystem for Linux 2 (WSL2), which provides a full Linux kernel on Windows 10, Windows 11, and Windows Server 2025, making shell scripting accessible to Windows developers without a separate Linux machine. WSL2 supports Ubuntu, Debian, Fedora, and other distributions and runs Bash natively, significantly expanding the audience for shell scripting beyond traditional UNIX system administrators.


Why Shell Scripting Remains Relevant in 2025

The Unix philosophy — small tools that do one thing well, connected by pipelines — remains the foundation of modern DevOps automation, CI/CD pipelines, container orchestration, and system administration. Shell scripts are the execution layer that connects these tools. Bash is the lingua franca of automation across the industry:

  • GitHub Actions workflows use the run: key to execute shell script blocks directly in the CI environment
  • GitLab CI script: sections execute as Bash by default on Linux runners
  • Jenkins shell build steps call shell scripts for build, test, and deployment tasks
  • Docker RUN instructions in Dockerfiles are shell commands executed during image construction
  • Kubernetes init containers, liveness probes, and readiness probes use shell scripts for health checking and initialization
  • Every Linux server — whether physical, virtual, or containerized — is administered through a shell

Understanding shell scripting is not optional for anyone working in system administration, platform engineering, or DevOps. The fundamentals covered in this course apply directly to production automation work regardless of the specific toolchain or cloud platform.


Bash — The Dominant Shell

Bash (the Bourne Again Shell) is the de facto standard for portable shell scripts and the default shell on most Linux distributions. It has received steady improvements across four major releases from 2019 to 2025, each adding features that make scripting safer, more expressive, and more precise without breaking compatibility with existing scripts.

Bash Version Timeline

Bash 5.0 (2019) introduced EPOCHSECONDS and EPOCHREALTIME for high-precision timestamp access without calling an external date command, SRANDOM for non-repeating random values, improvements to associative arrays, and an enhanced wait builtin for process synchronization.

Bash 5.1 (2020) added case-modification parameter expansions (${var^}, ${var,,} and related forms) and improved error handling in subshell contexts.

Bash 5.2 (2022) rewrote command substitution parsing for better error detection, introduced the patsub_replacement shell option, added ${var@k} expansion for associative array key access, and added the globskipdots option to exclude dot files from glob expansion.

Bash 5.3 (July 2025) is the current release and introduces the most significant new syntax in years. New command substitution forms ${ command; } and ${| command; } execute in the current shell context rather than a subshell, eliminating a fork in performance-sensitive scripts and allowing results to go directly to the REPLY variable. The new GLOBSORT variable controls how pathname expansion results are sorted — by name, size, or modification time, ascending or descending. Additional improvements include source -p for sourcing from a specific path, compgen -V for variable completion, read -E for readline editing, and improved printf conformance with C23.

Modern Bash Best Practices

Regardless of the Bash version in use, the following practices apply to every production shell script:

  • #!/usr/bin/env bash as the shebang line — locates Bash via the PATH rather than hardcoding /bin/bash, which may differ across distributions
  • set -euo pipefail at the top of every script — exits on error (-e), treats unset variables as errors (-u), and propagates pipeline failures (-o pipefail)
  • Always quote variables: "$variable" not $variable — prevents word splitting and glob expansion on variable values
  • Use [[ ]] instead of [ ] for conditionals in Bash — safer handling of empty strings and pattern matching
  • Use $(command) instead of backticks for command substitution — readable, nestable, and correctly handled by syntax highlighters and ShellCheck

POSIX sh is the most portable shell — scripts written to the POSIX standard run on any UNIX-like system including macOS, Linux, and BSD. Bash extends POSIX sh with arrays, [[ ]], process substitution, and other features that improve safety and expressiveness but reduce portability to non-Bash environments. The shebang line declares which interpreter the script requires: #!/bin/sh for maximum portability, #!/usr/bin/env bash for Bash-specific features.

Alternative Shells and Modern Innovations

The most significant shell scripting innovation since 2019 has occurred outside Bash, in a set of alternative shells that address longstanding limitations of the traditional text-stream paradigm — fragile text parsing, weak typing, and error-prone pipelines.

Nushell (Nu) is the most significant paradigm shift in shell design in decades. Rather than treating all data as plain text streams, Nushell treats everything as structured data — tables, records, and lists. Pipelines pass typed data between commands. Nushell provides native support for JSON, YAML, CSV, TOML, SQLite, and Excel files, allowing direct querying and transformation without intermediate tools like jq or awk. This makes Nushell particularly well-suited for data-heavy scripting, log analysis, and API response processing.

Oils (OSH and YSH) takes a different approach. OSH is a highly compatible modern reimplementation of POSIX/Bash with better error messages, improved tracing, and stricter parsing — it is designed as a drop-in replacement that runs existing Bash scripts while exposing their latent bugs. YSH is a new language built on top of OSH with real data structures, cleaner syntax, and an explicit upgrade path from Bash for teams that want to modernize their scripting without abandoning the Unix model.

Fish (the Friendly Interactive Shell) provides an excellent interactive terminal experience with autosuggestions, syntax highlighting, and tab completion that works out of the box without configuration. Fish is intentionally not POSIX-compatible — scripts written for Fish are not portable to Bash or sh environments. Fish is best suited for interactive terminal use rather than automation scripts.

Other active projects include Elvish, Murex, and Rust-based shell implementations (Brush, nsh) that prioritize memory safety and performance. The Rust ecosystem has also produced faster, safer rewrites of classic coreutils tools that are increasingly used inside shell scripts: ripgrep as a replacement for grep, bat as a replacement for cat, and eza as a replacement for ls.


Modern Shell Scripting Tooling

A set of modern companion tools has become standard practice alongside shell scripts in professional environments:

  • ShellCheck (shellcheck.net) — the standard static analysis tool for shell scripts. ShellCheck detects unquoted variables, incorrect conditionals, deprecated syntax, portability issues, and common logic errors before the script runs. It integrates with VS Code, IntelliJ IDEA, Vim, Neovim, and most CI/CD pipelines. Running ShellCheck before committing a shell script is the equivalent of a compiler warning pass — it catches errors that would otherwise surface only in production.
  • fzf — a fast, general-purpose fuzzy finder for the command line. Used inside shell scripts to provide interactive filtering of files, processes, git branches, and command history.
  • ripgrep (rg) — a faster alternative to grep that respects .gitignore rules, supports PCRE2 regular expressions, and searches recursively by default. Commonly used inside shell scripts for log analysis and codebase searching.
  • jq and yq — command-line JSON and YAML processors used inside shell scripts to parse API responses, configuration files, and structured data without writing a full Python or Ruby script.
  • just — a command runner that serves as a modern alternative to make for defining and running project tasks. just recipes call shell scripts and provide a clean interface for build, test, lint, and deploy workflows.
  • bat and eza — syntax-highlighted replacements for cat and ls, commonly aliased in shell configurations and used in interactive scripting workflows.

Course Objectives

After completing this course, you will be able to:

  1. Define a shell program and how it interacts with your UNIX system
  2. List the components that make up all shell scripts
  3. Describe the differences between popular shells
  4. Use different types of shell variables to hold data values
  5. Create coherent script objectives and designs
  6. Read and write files from within a script
  7. Define appropriate tests for conditions in a script
  8. Use different looping operations to control script flow
  9. Redirect input and output to control how data is handled in a script

The Series

Creating Basic UNIX Shell Scripts is the first of two courses in the UNIX Shell Programming series. In the next lesson, you will examine the course prerequisites.


SEMrush Software 1 SEMrush Banner 1