|

Linux CLI 53 🐧 shell scripts introduction

nano myscript.sh

#!/bin/bash

# This is a comment
echo "Hello, World!"

# save and exit

chmod +x myscript.sh

./myscript.sh

A shell script is a plain-text file full of shell commands that the system runs for you, in order, automatically. Instead of typing the same sequence of commands over and over, you write them once and run the script. It’s the simplest form of programming on Linux — and one of the most useful.

Key point: A shell script is interpreted, not compiled. The shell reads it line by line and executes each command. No build step, no binary — just a text file with execute permission.


a – what is a shell script

A shell script is a sequence of commands written in a plain-text file that is executed by a Unix or Linux shell. This script automates the execution of tasks and can be used for a variety of purposes.

Purpose:

  • Helps automate repetitive tasks, making them faster and less error-prone
  • Turns a series of manual steps into a single command
  • Captures knowledge — the script documents what needs to happen

Interpreted language:

  • Interpreted by the shell (like bash), not compiled
  • The shell reads the file and executes each command in turn
  • If a command fails, the shell moves to the next line (unless you tell it not to)

Command-based:

  • Consists of a series of commands that can be run manually in the terminal
  • Anything you can type at the prompt, you can put in a script
  • Pipes, redirects, variables, and globbing all work the same way

Extensibility:

  • Can include control structures like loops, conditionals, and functions
  • Can accept arguments and read user input
  • Can call other programs, scripts, and system utilities

Portability:

  • Can often be made portable across different Unix-like systems
  • POSIX-compliant scripts run on sh, bash, dash, ksh, and zsh
  • Bash-specific features limit portability to systems with bash

Common uses:

Use caseExample
AutomationBackups, log rotation, cleanup
DeploymentBuild, test, and release code
System administrationUser management, monitoring
Batch processingConvert files, resize images
Scheduled tasksCron jobs, systemd timers
Glue between toolsChain commands into pipelines

A minimal script:

#!/bin/bash
# This is a comment
echo "Hello, World!"

That’s it. Two lines — a shebang and a command. Save it, make it executable, run it.

What makes a script a script:

┌──────────────────────────────────────────────┐
│           Anatomy of a shell script          │
│                                              │
│  #!/bin/bash          ← shebang (interpreter)│
│                                              │
│  # Comments            ← ignored by the shell│
│                                              │
│  VAR="value"           ← variables           │
│  echo "$VAR"           ← commands            │
│                                              │
│  if [ ... ]; then      ← conditionals        │
│    ...                 │                     │
│  fi                    │                     │
│                        │                     │
│  for i in ...; do      ← loops               │
│    ...                 │                     │
│  done                  │                     │
│                        │                     │
│  myfunc() {            ← functions           │
│    ...                 │                     │
│  }                     │                     │
│                                              │
│  exit 0                ← exit status         │
│                                              │
└──────────────────────────────────────────────┘

b – How to write a shell script

Writing a shell script is a six-step process. Once you’ve done it a few times, it becomes second nature.

Step 1 — Open a text editor

Use any editor you’re comfortable with:

EditorCommand
nanonano myscript.sh
vimvim myscript.sh
vivi myscript.sh
geditgedit myscript.sh
katekate myscript.sh

The .sh extension is a convention, not a requirement — but it makes it clear the file is a shell script.

Step 2 — Add the shebang line

The shebang is the very first line of the script:

#!/bin/bash

It tells the system which interpreter to use. Without it, the script might be run by the wrong shell or fail entirely.

Common shebangs:

ShebangInterpreter
#!/bin/bashBash
#!/bin/shPOSIX shell (often dash)
#!/usr/bin/env bashBash, found via PATH
#!/usr/bin/env python3Python 3
#!/usr/bin/env perlPerl

Tip: #!/usr/bin/env bash is more portable than #!/bin/bash because it locates bash via your PATH rather than hardcoding its location.

Step 3 — Write your script

Add your commands, one per line. Here’s an example:

#!/bin/bash

# This is a comment
echo "Hello, World!"

# Use a variable
NAME="Kronos"
echo "Hello, $NAME!"

# Run a command
date

Step 4 — Save and exit

In nano, press Ctrl+O, then Enter, then Ctrl+X.
In vim, press Esc, then type :wq and press Enter.

Step 5 — Make the script executable

A script needs execute permission to be run directly:

chmod +x myscript.sh

Verify:

ls -l myscript.sh
-rwxr-xr-x 1 kronos kronos 123 Jan 15 10:00 myscript.sh
#  ^^^ execute bits are set

Step 6 — Run the script

./myscript.sh
Hello, World!
Hello, Kronos!
Mon Jan 15 10:00:00 UTC 2024

The ./ is required — it tells the shell to look in the current directory. Without it, the shell searches your PATH and won’t find your script.

Alternative ways to run a script:

# Explicitly with bash (no execute permission needed)
$ bash myscript.sh

# With sh
$ sh myscript.sh

# As a command if it's in your PATH
$ mv myscript.sh ~/bin/
$ myscript.sh

In a shell script you can have:

FeatureExample
VariablesNAME="Kronos"
Conditionalsif [ -f file ]; then ... fi
Loopsfor i in 1 2 3; do ... done
Functionsmyfunc() { echo "hi"; }
Arguments$1, $2, $@
User inputread -p "Name: " name
Command substitutionTODAY=$(date +%F)
Exit codesexit 0

You can also take input from the user:

#!/bin/bash

read -p "What is your name? " name
echo "Hello, $name!"
$ ./greet.sh
What is your name? Kronos
Hello, Kronos!

A slightly bigger example:

#!/bin/bash

# backup.sh — back up a directory with a timestamp

SRC="$1"
DST="$2"

if [ -z "$SRC" ] || [ -z "$DST" ]; then
    echo "Usage: $0 <source> <destination>"
    exit 1
fi

if [ ! -d "$SRC" ]; then
    echo "Error: $SRC is not a directory"
    exit 1
fi

STAMP=$(date +%F-%H%M)
ARCHIVE="$DST/backup-$STAMP.tar.gz"

tar -czf "$ARCHIVE" "$SRC"
echo "Backup created: $ARCHIVE"
$ chmod +x backup.sh
$ ./backup.sh /home/kronos/docs /backup
Backup created: /backup/backup-2024-01-15-1000.tar.gz

Complete Example Session

# ============================================
# PART 1: CREATE THE SCRIPT
# ============================================

$ nano myscript.sh

In nano, type:

#!/bin/bash

# This is a comment
echo "Hello, World!"

Save with Ctrl+O, Enter, exit with Ctrl+X.

# ============================================
# PART 2: VERIFY THE FILE
# ============================================

$ cat myscript.sh
#!/bin/bash

# This is a comment
echo "Hello, World!"

$ ls -l myscript.sh
-rw-r--r-- 1 kronos kronos 52 Jan 15 10:00 myscript.sh
# Note: no execute permission yet

# ============================================
# PART 3: TRY TO RUN IT
# ============================================

$ ./myscript.sh
bash: ./myscript.sh: Permission denied

# ============================================
# PART 4: MAKE IT EXECUTABLE
# ============================================

$ chmod +x myscript.sh
$ ls -l myscript.sh
-rwxr-xr-x 1 kronos kronos 52 Jan 15 10:00 myscript.sh
# Execute bits are now set

# ============================================
# PART 5: RUN IT
# ============================================

$ ./myscript.sh
Hello, World!

# ============================================
# PART 6: RUN WITHOUT EXECUTE PERMISSION
# ============================================

$ chmod -x myscript.sh
$ bash myscript.sh
Hello, World!
# Works because bash reads the file

# ============================================
# PART 7: ADD VARIABLES AND COMMANDS
# ============================================

$ cat > greet.sh << 'EOF'
#!/bin/bash

# A script with a variable
NAME="Kronos"
echo "Hello, $NAME!"
echo "Today is $(date +%A)"
EOF

$ chmod +x greet.sh
$ ./greet.sh
Hello, Kronos!
Today is Monday

# ============================================
# PART 8: TAKE USER INPUT
# ============================================

$ cat > ask.sh << 'EOF'
#!/bin/bash

read -p "What is your name? " name
echo "Hello, $name!"
EOF

$ chmod +x ask.sh
$ ./ask.sh
What is your name? Alice
Hello, Alice!

# ============================================
# PART 9: USE COMMAND-LINE ARGUMENTS
# ============================================

$ cat > args.sh << 'EOF'
#!/bin/bash

echo "Script: $0"
echo "First arg: $1"
echo "Second arg: $2"
echo "All args: $@"
echo "Number of args: $#"
EOF

$ chmod +x args.sh
$ ./args.sh hello world
Script: ./args.sh
First arg: hello
Second arg: world
All args: hello world
Number of args: 2

# ============================================
# PART 10: CONDITIONALS AND LOOPS
# ============================================

$ cat > check.sh << 'EOF'
#!/bin/bash

if [ -f /etc/passwd ]; then
    echo "/etc/passwd exists"
else
    echo "/etc/passwd is missing!"
fi

for i in 1 2 3; do
    echo "Number: $i"
done
EOF

$ chmod +x check.sh
$ ./check.sh
/etc/passwd exists
Number: 1
Number: 2
Number: 3

Quick Reference

Shebangs

ShebangInterpreter
#!/bin/bashBash
#!/bin/shPOSIX shell
#!/usr/bin/env bashBash via PATH
#!/usr/bin/env python3Python 3
#!/usr/bin/env perlPerl

Creating a Script

StepCommand
1. Open editornano myscript.sh
2. Add shebang#!/bin/bash
3. Write commandsecho "Hello"
4. Save & exitCtrl+O, Enter, Ctrl+X
5. Make executablechmod +x myscript.sh
6. Run./myscript.sh

Running a Script

MethodCommand
Direct./myscript.sh
With bashbash myscript.sh
With shsh myscript.sh
From PATHmyscript.sh (after mv to ~/bin)

Script Features

FeatureSyntax
Comment# comment
VariableVAR="value"
Use variable$VAR or ${VAR}
Command substitution$(command)
Argument$1, $2, $@
Argument count$#
Script name$0
User inputread -p "Prompt: " var
Exitexit 0
Conditionalif [ ... ]; then ... fi
Loopfor i in ...; do ... done
Functionname() { ... }

File Permissions

CommandEffect
chmod +x FILEAdd execute
chmod -x FILERemove execute
chmod 755 FILErwxr-xr-x
chmod 700 FILErwx——
ls -l FILECheck permissions

Best Practices

Do This:

# Always include a shebang
#!/bin/bash                           # ✅

# Comment your scripts
# This script backs up files          # ✅

# Use meaningful variable names
BACKUP_DIR="/backup"                  # ✅

# Quote variables
echo "$NAME"                          # ✅

# Make scripts executable
chmod +x myscript.sh                  # ✅

# Check arguments
if [ -z "$1" ]; then
    echo "Usage: $0 <arg>"
    exit 1
fi                                    # ✅

# Use exit codes
exit 0                                # ✅

# Test with bash first
bash myscript.sh                      # ✅

Don’t Do This:

# Don't forget the shebang
echo "Hello"                          # ❌ may fail

# Don't use unquoted variables with spaces
echo $NAME                            # ❌ if NAME has spaces

# Don't assume a specific directory
cd /tmp                               # ⚠️  use absolute paths

# Don't ignore errors silently
rm -rf $DIR/*                         # ❌ dangerous if DIR empty

# Don't use tabs and spaces inconsistently
if [ ... ]; then
	echo "x"                          # ⚠️  use consistent indent

# Don't name your script after an existing command
ls.sh                                 # ⚠️  confusing

# Don't hardcode paths that may change
/usr/local/bin/myapp                  # ⚠️  use $PATH lookup

Common Pitfalls

PitfallProblemSolution
No shebangWrong interpreterAdd #!/bin/bash
No execute bitPermission deniedchmod +x
Running without ./Command not foundUse ./script.sh
Unquoted variablesWord splittingUse "$VAR"
CRLF line endingsbad interpreter errordos2unix script.sh
Spaces around =Variable not setVAR=value (no spaces)
Relative pathsFails from other dirsUse absolute paths
Not checking argsCrashes on missing inputValidate $1, $2

Real-World Examples

1. Hello World

#!/bin/bash
echo "Hello, World!"

2. Greet the User

#!/bin/bash
read -p "What is your name? " name
echo "Hello, $name!"

3. Show the Date

#!/bin/bash
echo "Today is $(date +%A), $(date +%F)"

4. List Files with Details

#!/bin/bash
ls -lh "$1"

5. Check if a File Exists

#!/bin/bash
if [ -f "$1" ]; then
    echo "$1 exists"
else
    echo "$1 not found"
    exit 1
fi

6. Loop Over Arguments

#!/bin/bash
for arg in "$@"; do
    echo "Argument: $arg"
done

7. Simple Backup Script

#!/bin/bash
SRC="$1"
DST="$2"
STAMP=$(date +%F-%H%M)
tar -czf "$DST/backup-$STAMP.tar.gz" "$SRC"
echo "Backup saved to $DST/backup-$STAMP.tar.gz"

8. Disk Usage Warning

#!/bin/bash
THRESHOLD=80
USAGE=$(df / | awk 'NR==2 {print $5}' | tr -d '%')
if [ "$USAGE" -gt "$THRESHOLD" ]; then
    echo "Warning: disk usage is ${USAGE}%"
fi

9. Rename All .txt Files

#!/bin/bash
for f in *.txt; do
    mv "$f" "${f%.txt}.md"
done

10. Count Lines in Files

#!/bin/bash
for f in "$@"; do
    printf "%5d  %s\n" "$(wc -l < "$f")" "$f"
done

11. Check If a Service Is Running

#!/bin/bash
SERVICE="sshd"
if systemctl is-active --quiet "$SERVICE"; then
    echo "$SERVICE is running"
else
    echo "$SERVICE is not running"
fi

12. Simple Menu

#!/bin/bash
echo "1) Show date"
echo "2) Show uptime"
echo "3) Quit"
read -p "Choice: " choice

case "$choice" in
    1) date ;;
    2) uptime ;;
    3) exit 0 ;;
    *) echo "Invalid choice" ;;
esac

13. Log Rotation

#!/bin/bash
LOG="/var/log/myapp.log"
if [ -f "$LOG" ]; then
    mv "$LOG" "$LOG.$(date +%F)"
    touch "$LOG"
    echo "Log rotated"
fi

14. Deploy Script

#!/bin/bash
set -e  # exit on error
git pull
npm install
npm run build
sudo systemctl restart myapp
echo "Deployed successfully"

15. Generate a Report

#!/bin/bash
echo "=== System Report ==="
echo "Date: $(date)"
echo "Host: $(hostname)"
echo "Uptime: $(uptime -p)"
echo "Disk:"
df -h /
echo "Memory:"
free -h

Visual: Script Execution

┌──────────────────────────────────────────────┐
│           How a script runs                  │
│                                              │
│  $ ./myscript.sh                             │
│       │                                      │
│       ▼                                      │
│  ┌────────────────────────────────────────┐  │
│  │  Kernel reads the shebang              │  │
│  │  #!/bin/bash                           │  │
│  │  → launches /bin/bash                  │  │
│  └────────────┬───────────────────────────┘  │
│               │                              │
│               ▼                              │
│  ┌────────────────────────────────────────┐  │
│  │  Bash reads the script line by line    │  │
│  │                                        │  │
│  │  # comment      ← ignored              │  │
│  │  echo "Hello"   ← executed             │  │
│  │  date           ← executed             │  │
│  │  exit 0         ← returns 0            │  │
│  └────────────┬───────────────────────────┘  │
│               │                              │
│               ▼                              │
│  Output to terminal                          │
│                                              │
└──────────────────────────────────────────────┘

Summary

ConceptMeaning
Shell scriptText file of shell commands
Shebang#!/bin/bash — picks the interpreter
Execute bitNeeded to run ./script.sh
VariableVAR="value"
Use variable$VAR or ${VAR}
Argument$1, $2, $@
User inputread -p "Prompt: " var
Conditionalif [ ... ]; then ... fi
Loopfor i in ...; do ... done
Functionname() { ... }
Exit codeexit 0 (success)

Key takeaways:

  • A shell script is a plain-text file of commands executed by the shell
  • It’s interpreted, not compiled — no build step
  • The shebang (#!/bin/bash) must be the first line — it picks the interpreter
  • Six steps to write one: open, shebang, write, save, chmod +x, run
  • Run with ./script.sh — the ./ tells the shell to look in the current directory
  • Scripts can have variables, conditionals, loops, functions, arguments, and user input
  • Use chmod +x to make a script executable
  • Use bash script.sh if you don’t want to set the execute bit
  • Quote your variables"$VAR", not $VAR
  • Scripts are for automation, deployment, system administration, and batch processing

Remember: A shell script is just commands in a file. Start with #!/bin/bash, add echo "Hello, World!", save, chmod +x, and run ./myscript.sh. From there, add variables, arguments, conditionals, and loops as you need them. Scripts are the fastest way to automate anything you do more than once. Learn to write them, and you’ll never type the same sequence of commands twice.


Stop using slow, ad-bloated tool sites! 🤮

🔎 Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)

⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free

🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!