Cyberlium

Linux › Module 6 › Lesson 4

BeginnerModule 6Lesson 4/6

Bash Scripting Basics

Write your first bash scripts with variables, if, and loops

15 min+24 XP3 quiz
Module progress4 of 6

Opening

Stop repeating yourself

If you ran the same five commands twice today, the third time belongs in a file. A bash script is plain text the shell executes in order — automation for analysts, admins, and anyone tired of retyping whoami, pwd, and date into a notes folder. This lesson is literacy, not wizardry: shebang, variables, quoting, if tests, exit codes, chmod +x, and a tiny loop pattern you can reuse safely. Unquoted $1 is not a style nit. It is how a filename with spaces — or a crafted argument — becomes many words the script never intended to see. You will practice only under $HOME/cyberlium-lab on a machine you own. No eval of user input. No destructive rm of arguments.

1. Shebang and chmod +x

Line 1 should be #!/bin/bash (the shebang). It tells the kernel which interpreter to use when you run ./script.sh. Without a shebang, some environments may still run the file with a default shell — but you should not rely on that. Be explicit. #!/usr/bin/env bash is another common form that searches PATH for bash.

Without execute permission, the kernel will not launch ./script.sh that way — chmod +x script.sh adds the execute bit for the owner (on a file you own under your home). You can always bash script.sh instead, which ignores the need for +x but still needs a readable file. Prefer chmod +x only on scripts you wrote and reviewed. Never chmod +x a mystery download "so it runs."

2. Variables, arguments, and why quotes are safety gear

NAME="analyst" stores a string. echo "User: $NAME" expands it. Quotes around the assignment keep spaces inside one value. When you expand, prefer "$NAME" so the result stays one word even if it contains spaces. Unquoted expansions undergo word splitting and globbing: a variable holding * can turn into a list of filenames in the current directory — a surprise you do not want in automation.

Positional arguments are $1, $2, and so on; $# is the count; "$@" is all arguments as separate quoted words when used correctly. A script that runs rm $1 (unquoted) is a classic accident: if $1 is My Report.txt, rm sees two arguments; if someone passes a glob or extra words, you may touch files you never named. Always "$1" unless you have a precise, documented reason not to. This course will not teach you to rm user input in the lab — quoting still matters for echo, mkdir, cat, and test.

Default values help: TARGET="${1:-$HOME/cyberlium-lab}" uses $1 if provided, otherwise a safe lab path. That pattern keeps scripts usable with zero arguments without inventing dangerous fallbacks like /.

3. if tests, [, and exit codes

Every command returns an exit status: 0 usually means success, non-zero means failure. echo $? prints the last status. Scripts should exit 0 when they did their job and a non-zero code when they cannot — so other scripts, cron wrappers, and CI can detect failure. Silent "success" on failure hides bugs until production.

if [ -d "$TARGET" ]; then … fi tests whether a path is a directory. [ is a command (test); the spaces around [ and ] are required. Quote "$TARGET" inside [ ] so a path with spaces is one operand. An unquoted empty variable can make [ ] parse as a broken test and behave surprisingly. Common tests: -f (regular file), -d (directory), -e (exists), -z (string empty), -n (string non-empty). Learn them slowly on files you own.

set -e near the top makes the script exit when a command fails (with some caveats around if and pipelines). It is not magic armor, but it beats continuing after a failed mkdir and writing into the wrong place. Combine with clear messages on stderr: echo "error..." >&2; exit 1.

4. A tiny loop without getting clever

for f in "$HOME/cyberlium-lab"/*.txt; do echo "$f"; done is a readable pattern for iterating files you already created. Quote "$f" inside the loop. Avoid for loops that expand untrusted globs over system directories. Keep loops inside your lab tree. Clever one-liners that parse ls are fragile; prefer globs or find you understand, and never pipe find into a destructive command for "practice."

5. Wrong vs right: unquoted $1

Worked failure mode — "it worked on my one-word filename":

  • Wrong

    A helper script does cat $1 > report.txt. A teammate runs ./helper.sh "auth log copy.txt". The shell splits the name. cat looks for auth, then log, then copy.txt. Wrong files, wrong error, or worse if the next line were a destructive command. A hostile argument with * would expand to whatever sits in the current directory. "It worked on notes.txt" is not a security review.

  • Right

    Use "$1", quote variables in tests, and treat arguments as data — not as raw shell code. Start scripts with a shebang, chmod +x only on files you wrote under $HOME/cyberlium-lab, exit with a status that matches success or failure, and never eval "$1".

6. Practical: a tiny quoted script you own

Write this under $HOME/cyberlium-lab only on YOUR VM or WSL. Do not cat or rm paths from strangers. No destructive commands in the script. If ./hello.sh says Permission denied, check chmod +x before inventing SUID "fixes."

Command guide

hello.sh — shebang, quotes, if, exit (your machine)

Command — copy this

mkdir -p "$HOME/cyberlium-lab"
cd "$HOME/cyberlium-lab"

Command — copy this

cat > hello.sh << 'EOF'
#!/bin/bash
set -e
TARGET="${1:-$HOME/cyberlium-lab}"
echo "Hello from Cyberlium"
echo "User: $(whoami)"
echo "PWD: $(pwd)"
if [ -d "$TARGET" ]; then
  echo "Directory exists: $TARGET"
  # Tiny safe loop over .txt files if any exist
  shopt -s nullglob
  for f in "$TARGET"/*.txt; do
    echo "Found text file: $f"
  done
  exit 0
else
  echo "Not a directory: $TARGET" >&2
  exit 1
fi
EOF

Command — copy this

chmod +x hello.sh
./hello.sh "$HOME/cyberlium-lab"
echo "exit code was $?"

Show why quotes matter (safe demo — echo only)

Command — copy this

demo='two words'
echo unquoted: $demo
echo quoted: "$demo"

DO NOT: rm $1 DO NOT: eval "$1" DO NOT: chmod +x scripts you did not write and do not understand DO NOT: set a default TARGET to / or another system path

Mission: shebang, +x, and quotes

Create $HOME/cyberlium-lab/hello.sh with a shebang, chmod +x, and run ./hello.sh. Confirm it prints whoami and uses "$TARGET" or "$1" in a test. Optional: add a for loop that only echoes *.txt names under your lab folder. Write one sentence: "Unquoted $1 is dangerous because ___."

Stuck? Ask Cyberlium AI Mentor

If shebang, chmod +x, or quoting feels fuzzy, ask Cyberlium AI Mentor for a hint — not an eval-based "clever" parser. Try: "Hint only: why does ./script.sh fail with Permission denied?" Or: "Hint only: what goes wrong if I cat $1 without quotes?" Practice only on your own lab files.

You can write a shebang script, set the execute bit, branch on a test, quote expansions so arguments stay data, and exit with a status callers can trust. Next — Lab — Mini Automation Script — you will put whoami, pwd, and date into $HOME/cyberlium-lab/sysinfo.sh and run it.

Knowledge Check

1

APPLY: ./hello.sh says Permission denied even though the file exists and starts with #!/bin/bash. Most likely missing piece?

Multiple choice

Knowledge Check

2

APPLY: Why is cat $1 (unquoted) dangerous compared with cat "$1"?

Multiple choice

Knowledge Check

3

APPLY: True or False: A script should exit 0 on success and non-zero when it cannot do its job, so callers can detect failure.

True or False

← Previous

Answer all 3 knowledge checks to continue. (0/3 answered)