October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk8 min

Unix Shell Scripting: A Beginner’s Guide

A practical beginner’s guide to Unix shell scripting, with runnable Bash examples and clear advice on quoting, arguments, errors, and POSIX portability.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A Unix shell script is a text file of commands that a shell reads and runs. It lets you combine ordinary utilities into a repeatable task—for example, creating a directory and placing selected files inside it. To write reliable scripts, start by understanding how the shell parses text, then add quoted arguments, variables, tests, loops, and functions. This guide uses Bash for its examples; portability notes explain what to check if your script must run under POSIX sh.

What a shell does—and what a script is

The GNU Project’s Bash Reference Manual describes a Unix shell as both a command interpreter and a programming language. At the prompt, it interprets commands you enter; in a script, it reads commands from a file. Either way, the shell can run programs and connect them to other programs, while its language adds variables, decisions, repetition, and functions.

The examples below target Bash. The manual-specific behavior discussed here is documented in the GNU Bash Reference Manual, Edition 5.3, updated May 18, 2025. Other shells can differ, so do not assume every Bash example works unchanged in every Unix-like environment.

How to create and run a script

A script is plain text, not a compiled program. Its first line can name the interpreter; this line is called the shebang.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
  1. Create a file named hello.sh with these lines:
    #!/usr/bin/env bash
    printf 'Hello, %sn' "$USER"
  2. Run it explicitly with Bash: bash hello.sh. This does not require the file to be executable.
  3. Alternatively, make it executable and run it by path:
    chmod +x hello.sh
    ./hello.sh

#!/usr/bin/env bash asks the environment to find Bash through PATH. If Bash is unavailable or not on that path, execution fails; use an interpreter available on the target system. Running ./hello.sh also requires execute permission and a path to the file, such as ./ for the current directory.

Commands, arguments, and the shell’s parsing order

Consider printf '%sn' 'two words'. The shell treats this as a command name followed by arguments. In broad terms, Bash reads input, recognizes words and operators according to quoting rules, parses the command, performs expansions, applies redirections, executes it, and makes the resulting exit status available. This is why shell text is not simply passed unchanged to a program.

  • Unquoted spaces separate words: one two is ordinarily two arguments.
  • Unquoted wildcard characters such as * can expand to matching filenames before the command runs.
  • Operators such as | and > have shell meaning when unquoted.

When exact argument boundaries matter, quote expansions and text deliberately rather than relying on how a command happens to handle spaces.

Quoting: keep text from becoming syntax

Quoting suppresses some of the special meanings the shell assigns to characters. Bash’s quoting rules distinguish single quotes, double quotes, and backslashes.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Single quotes preserve literal text

Everything between single quotes is treated literally, including dollar signs and wildcard characters. A single quote cannot appear inside a single-quoted string by simply placing a backslash before it.

printf '%sn' 'Price: $5; *.txt stays literal'

Double quotes preserve argument boundaries but allow selected expansions

Inside double quotes, Bash still expands parameters such as $name and command substitutions such as $(date), while preserving the result as one argument. For example:

name='Ada Lovelace'
printf 'Hello, %sn' "$name"

Use "$name" rather than $name in ordinary command arguments. Without quotes, spaces in the value can split it into several words, and wildcard characters may be expanded against filenames.

Use command substitution for a command’s output

$(...) runs a command and substitutes its output. Quoting the substitution prevents its output from being split or treated as a filename pattern:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
today="$(date +%F)"
printf 'Date: %sn' "$today"

Command substitution removes trailing newline characters from the captured output. Avoid using it when the exact output, including trailing newlines, must be preserved.

Variables and script parameters

Assign a value with no spaces around the equals sign, then expand it with a dollar sign. In Bash, a variable assignment by itself does not print anything.

output_dir="$HOME/reports"
printf 'Reports will go in %sn' "$output_dir"

Shell variables are not declared with a type in this example. Quote variable expansions when using them as arguments so the value stays one argument even if it contains spaces.

Read arguments passed to the script

Positional parameters let a script use its command-line arguments: $1 is the first, $2 the second, and $# the number of arguments. Use "$@" when forwarding all arguments while preserving each argument as a separate item.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#!/usr/bin/env bash
if [ "$#" -ne 1 ]; then
  printf 'Usage: %s DIRECTORYn' "$0" >&2
  exit 2
fi
printf 'Requested directory: %sn' "$1"

$0 is the name or path used to invoke the script. In the example, the script checks that exactly one argument was supplied before using it.

Exit status: detect success and failure

Commands return an exit status: conventionally, 0 means success and a nonzero value indicates some kind of failure. The shell stores the most recent command’s status in $?, but another command overwrites it, so check it immediately if you need to inspect it directly.

cp -- "$source_file" "$destination"
status=$?
if [ "$status" -eq 0 ]; then
  printf 'Copy completedn'
else
  printf 'Copy failed with status %sn' "$status" >&2
  exit "$status"
fi

Often it is clearer to put a command directly in an if statement, which tests its status:

if cp -- "$source_file" "$destination"; then
  printf 'Copy completedn'
else
  printf 'Copy failedn' >&2
  exit 1
fi

The -- option ends option parsing for utilities that support it, which helps when a filename begins with a hyphen. Utility options are not universal, so check the specific command’s documentation when writing for multiple systems.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Conditionals: choose what to do

An if statement runs commands based on whether a test or other command succeeds. The bracket form below, [ ... ], is a command; leave spaces around its brackets.

if [ -f "$1" ]; then
  printf 'Regular file exists: %sn' "$1"
else
  printf 'Not a regular file: %sn' "$1" >&2
  exit 1
fi

Here -f tests whether the path names a regular file. Common file checks include -d for a directory and -e for an existing path in Bash. String and numeric tests are also available; use the test expression appropriate to the value rather than comparing everything as text.

Loops: repeat a task safely

A for loop can process a list of arguments. In Bash, "$@" expands to the script’s arguments as separate items, including arguments containing spaces.

for item in "$@"; do
  printf 'Item: %sn' "$item"
done

To loop over files matching a pattern, quote the pattern only if you want it treated literally. This Bash example processes matching text files in the current directory:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
for file in ./*.txt; do
  [ -e "$file" ] || continue
  printf 'Found: %sn' "$file"
done

If there are no matches, Bash ordinarily leaves an unmatched pattern unchanged. The [ -e "$file" ] || continue check skips that literal pattern. Bash options can change wildcard behavior, so a script that changes shell options should do so intentionally.

A while loop repeats while its test command succeeds. For example, this reads lines from a file without splitting each line into separate words:

while IFS= read -r line; do
  printf '%sn' "$line"
done < input.txt

IFS= prevents trimming leading and trailing whitespace during the read, and -r prevents backslashes from being treated as escapes.

Functions: name a reusable group of commands

Functions help organize repeated work. In Bash, define one with this syntax:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
log() {
  printf '[%s] %sn' "$(date +%H:%M:%S)" "$*"
}

log 'Starting task'

Function arguments are available through positional parameters just as they are in a script. For messages where preserving argument boundaries matters, use "$@" rather than "$*". The example uses $* because it formats the arguments as one message string.

Redirection and pipelines: connect commands

Redirection changes where a command reads input or sends output. These operators are interpreted by the shell:

  • command > output.txt sends standard output to a file, replacing its previous contents.
  • command >> output.txt appends standard output.
  • command < input.txt reads standard input from a file.
  • command 2> errors.txt sends standard error to a file.

A pipeline, written with |, connects one command’s standard output to the next command’s standard input:

grep 'ERROR' application.log | wc -l

By default, a pipeline’s status in Bash is the status of its last command, so a failure earlier in the pipeline may not be reflected. Bash’s set -o pipefail makes a pipeline return a failing status if a command in it fails; that option is Bash-specific, not portable POSIX sh syntax.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Make a small script more reliable

This Bash example combines arguments, validation, quoting, a loop, and error handling to list regular files supplied on the command line. It prints a message for invalid input and exits with a nonzero status.

#!/usr/bin/env bash

if [ "$#" -lt 1 ]; then
  printf 'Usage: %s FILE...n' "$0" >&2
  exit 2
fi

for file in "$@"; do
  if [ -f "$file" ]; then
    printf '%sn' "$file"
  else
    printf 'Not a regular file: %sn' "$file" >&2
    exit 1
  fi
done

It expects at least one argument and stops at the first path that is not a regular file. If the desired behavior is to report every invalid path rather than stop, track failures and exit after the loop instead.

Portability: choose the shell your script needs

“Unix shell” does not name one identical language implementation. POSIX specifies important shell behavior, including flow control, program execution, input/output redirection, pipelines, argument handling, variable expansion, and quoting. Bash aims to implement the POSIX Shell and Tools portion, but its ordinary default behavior differs from POSIX in some areas. Bash also provides additional features.

For a script intended for Bash, use a Bash shebang such as #!/usr/bin/env bash and label Bash-only constructs. For a script intended to run with a POSIX shell, use a suitable sh shebang and avoid Bash-specific syntax. A script’s shebang identifies its intended interpreter; it does not make incompatible syntax portable. Bash’s POSIX mode changes some behavior to follow the standard more closely, but it is not a substitute for checking which shell features the script uses.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Troubleshoot common beginner errors

  • “Permission denied” when running ./script.sh: the file may not be executable. Run chmod +x script.sh, or invoke it as bash script.sh.
  • “Command not found” or the wrong interpreter: check the shebang and whether the named shell or command is installed and available through PATH.
  • A filename with spaces becomes several arguments: quote variable expansions and arguments, such as "$file".
  • A wildcard unexpectedly matches files: quote it to pass the literal characters, as in '*.txt', or use an appropriate escaped form.
  • A test reports a syntax error: in the [ ... ] form, put spaces after [ and before ], and quote variable expansions.
  • A script works in Bash but not when run with sh: it may use Bash-specific syntax. Run it with Bash or rewrite it using constructs specified for the target POSIX shell.
  • A pipeline appears successful despite an earlier failure: Bash normally uses the last command’s status for the pipeline. Consider set -o pipefail when the script targets Bash.

Or skip the browser setup

If your task is to capture a web page from a script, ScreenshotNeo provides a screenshot API and MCP server. A single GET request can return an image or PDF; see the ScreenshotNeo API documentation for parameters.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

ScreenshotNeo accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed. Its MCP server lets AI agents use screenshot tools, and the Free plan includes 1,000 screenshots per month with no card required; paid plans start at $5 for 3,000 screenshots.

Sign up for ScreenshotNeo free: 1,000 screenshots a month, no card.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. Shenzhen desk3 min
    HONOR Expands Beyond Smartphones With Humanoid Robot RevealHONOR said it unveiled its first humanoid robot at MWC 2026 and named shopping assistance, workplace inspections, and supportive companionship as intended uses. Later Robotics D1 claims and a reported…
  2. Cupertino desk5 min
    Apple Unveils AirPods Max 2: The Upgrade That Should Have Happened Years AgoAirPods Max 2 adds H2-powered audio features and Apple claims up to 1.5× more effective ANC, but its design, Smart Case, and 20-hour battery rating are unchanged. Wired lossless audio…
  3. Cupertino desk4 min
    Apple’s OLED Touch MacBooks Are Coming—but the Dynamic Island Is the Real GambleApple has not announced an OLED touchscreen MacBook, but reports point to high-end models arriving in late 2026 or early 2027. The reported Mac Dynamic Island could be useful, but…
Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.