ᛉ Yggdrasil

Linux

Bash

15 Sep 2026 · 2,582 words · 12 min

Contents

1. Core Concepts

1.1 What Bash Is

Bash stands for Bourne Again SHell. It is both:

  • An interactive command shell for running commands.
  • A scripting language for automating tasks.

Think of Bash as the glue of Linux operations. It connects commands, files, processes, environment variables, and text streams into repeatable workflows.

1.2 Shell Model

A shell sits between the user and the operating system.

User -> Terminal -> Bash -> Kernel -> System Resources

When a command is entered, Bash:

  1. Reads the input.
  2. Expands variables, wildcards, and substitutions.
  3. Resolves whether the command is a builtin, function, alias, or executable.
  4. Executes it.
  5. Returns output and an exit status.

1.3 Why Bash Matters

Bash is used for:

  • Linux administration.
  • CTF and lab automation.
  • Log parsing.
  • Enumeration helpers.
  • File and process management.
  • Lightweight reporting and wrappers around tools.

1.4 Exit Status

Every command returns an exit code.

  • 0 = success
  • Non-zero = failure or different status
ls /tmp
echo $?

This is critical for scripting because flow control usually depends on exit status, not printed text.


2. Shell Basics

2.1 Check Current Shell

echo $SHELL
ps -p $$

2.2 Bash Version

bash --version

2.3 Command Types

Bash resolves commands in roughly this order:

  • Aliases
  • Functions
  • Builtins
  • Executables in $PATH

Useful checks:

type cd
type ls
which ls
command -v python3

2.4 Builtins vs External Commands

  • Builtins run inside the shell process, examples: cd, echo, export, read.
  • External commands are binaries/scripts on disk, examples: /bin/ls, /usr/bin/grep.

This matters because builtins can modify the current shell environment directly.

2.5 Command Structure

command [options] [arguments]

Example:

ls -lah /var/log
  • ls = command
  • -lah = options
  • /var/log = argument

3. Navigation and Files

3.1 Current Directory

pwd

3.2 Change Directory

cd /etc
cd ..
cd ~
cd -
  • .. = parent directory
  • ~ = home directory
  • - = previous directory

3.3 List Files

ls
ls -l
ls -la
ls -lah

3.4 Create, Copy, Move, Delete

touch file.txt
mkdir notes
mkdir -p project/{src,docs,tmp}
cp file.txt backup.txt
cp -r dir1 dir2
mv old.txt new.txt
rm file.txt
rm -r folder
rm -rf folder

3.5 View File Content

cat file.txt
less file.txt
head -n 20 file.txt
tail -n 20 file.txt
tail -f app.log
nl -ba file.txt

3.6 Find Files

find /var/log -name "*.log"
find . -type f
find . -type d
find . -type f -size +10M
find . -type f -mtime -1

4. Input, Output, and Redirection

4.1 Standard Streams

Each process usually has three standard streams:

  • stdin = file descriptor 0
  • stdout = file descriptor 1
  • stderr = file descriptor 2
keyboard -> stdin
stdout   -> normal output
stderr   -> errors

4.2 Redirect Output

command > out.txt
command >> out.txt
command 2> err.txt
command > out.txt 2> err.txt
command &> all.txt
command > /dev/null 2>&1

4.3 Redirect Input

sort < names.txt

4.4 Here-Documents

cat <<EOF
line 1
line 2
EOF

Quoted heredoc disables expansion:

cat <<'EOF'
$HOME will not expand here
EOF

4.5 Here-Strings

grep root <<< "root:x:0:0"

5. Pipes and Text Processing

5.1 Pipes

A pipe sends stdout of one command into stdin of the next.

cat access.log | grep 404 | wc -l

Preferred shorter style when possible:

grep 404 access.log | wc -l

5.2 Core Text Tools

grep "error" app.log
grep -i "failed" auth.log
grep -r "password" .
cut -d: -f1 /etc/passwd
sort users.txt
sort -u users.txt
uniq names.txt
uniq -c names.txt
wc -l file.txt
tr 'a-z' 'A-Z' < file.txt
sed 's/http/https/g' urls.txt
awk '{print $1}' file.txt
column -t data.txt

5.3 Practical Pipelines

ss -ltn | tail -n +2 | wc -l
cut -d: -f1 /etc/passwd
grep -i "failed password" auth.log | awk '{print $(NF-3)}' | sort -u

5.4 xargs

cat hosts.txt | xargs -I{} ping -c 1 {}
find . -name "*.log" | xargs rm
find . -type f -print0 | xargs -0 sha256sum

6. Variables and Environment

6.1 Create Variables

name="zoro"
port=4444
path=/tmp

Use them:

echo "$name"
echo "$port"

6.2 Environment Variables

export TARGET=10.10.10.10
export WORDLIST=/usr/share/wordlists/rockyou.txt
printenv
env

6.3 Common Variables

echo "$HOME"
echo "$USER"
echo "$PATH"
echo "$PWD"
echo "$OLDPWD"
echo "$?"
echo "$$"

Useful special parameters:

  • $0 = script name
  • $1 .. $9 = positional args
  • $# = argument count
  • $@ = all arguments as separate words
  • $* = all arguments as one expansion context
  • $$ = current shell PID
  • $? = last exit code

6.4 Read User Input

read name
echo "Hello $name"
read -p "Target IP: " ip
read -s -p "Password: " pass; echo

7. Quoting and Expansion

This is one of the most important Bash topics.

7.1 Single Quotes

Everything inside single quotes is literal.

echo '$HOME'

7.2 Double Quotes

Variables and command substitutions expand.

echo "$HOME"
echo "User: $USER"

7.3 Unquoted Text

Unquoted expansions are subject to word splitting and globbing. This causes many bugs.

Bad:

file="my notes.txt"
cat $file

Good:

cat "$file"

7.4 Command Substitution

now=$(date)
user_count=$(cut -d: -f1 /etc/passwd | wc -l)

7.5 Arithmetic Expansion

x=5
y=7
echo $((x + y))

7.6 Brace Expansion

echo file{1..5}.txt
mkdir -p lab/{loot,scans,notes}

7.7 Globbing

ls *.txt
ls /var/log/*.log
  • * = any string
  • ? = single character
  • [abc] = one listed char
  • [0-9] = range

7.8 Tilde Expansion

cd ~
cat ~/.bashrc

8. Conditionals and Tests

8.1 if Statements

if [ -f /etc/passwd ]; then
  echo "file exists"
fi

8.2 if / else

if [ "$USER" = "root" ]; then
  echo "running as root"
else
  echo "not root"
fi

8.3 Test Forms

[ condition ]
[[ condition ]]
test condition

Prefer [[ ... ]] in Bash scripts because it is safer and more expressive.

8.4 File Tests

[ -e file ]
[ -f file ]
[ -d dir ]
[ -r file ]
[ -w file ]
[ -x file ]
[ -s file ]

8.5 String Tests

[[ -z "$var" ]]
[[ -n "$var" ]]
[[ "$a" = "$b" ]]
[[ "$a" != "$b" ]]

8.6 Numeric Tests

[ "$x" -eq 10 ]
[ "$x" -ne 10 ]
[ "$x" -lt 10 ]
[ "$x" -le 10 ]
[ "$x" -gt 10 ]
[ "$x" -ge 10 ]

8.7 Logical Operators

if [[ -f file && -r file ]]; then
  cat file
fi

if [[ "$port" -eq 80 || "$port" -eq 443 ]]; then
  echo "web port"
fi

8.8 case Statements

case "$1" in
  start) echo "starting" ;;
  stop) echo "stopping" ;;
  restart) echo "restarting" ;;
  *) echo "usage: $0 {start|stop|restart}" ;;
esac

9. Loops and Control Flow

9.1 for Loop

for host in 10.10.10.1 10.10.10.2 10.10.10.3; do
  ping -c 1 "$host"
done

9.2 while Loop

count=1
while [ "$count" -le 5 ]; do
  echo "$count"
  count=$((count + 1))
done

9.3 Read File Line by Line

while IFS= read -r line; do
  echo "$line"
done < hosts.txt

9.4 until Loop

until ping -c 1 10.10.10.10 >/dev/null 2>&1; do
  sleep 1
done

9.5 break and continue

for i in {1..10}; do
  [ "$i" -eq 5 ] && continue
  [ "$i" -eq 9 ] && break
  echo "$i"
done

10. Functions

10.1 Basic Function

say_hello() {
  echo "hello"
}

say_hello

10.2 Function Arguments

scan_host() {
  local host="$1"
  nmap -Pn "$host"
}

scan_host 10.10.10.10

10.3 Return vs Output

In Bash, return is mainly for exit codes, not strings.

is_root() {
  [ "$EUID" -eq 0 ]
}

if is_root; then
  echo "yes"
fi

Return text through stdout:

get_date() {
  date +%F
}

today=$(get_date)

10.4 local Variables

foo() {
  local tmp="value"
  echo "$tmp"
}

11. Arrays and String Handling

11.1 Arrays

hosts=(10.10.10.10 10.10.10.20 10.10.10.30)
echo "${hosts[0]}"
echo "${hosts[@]}"
echo "${#hosts[@]}"
for host in "${hosts[@]}"; do
  echo "$host"
done

11.2 String Length

msg="bash scripting"
echo "${#msg}"

11.3 Substring

echo "${msg:0:4}"

11.4 Replace in Strings

file="report.txt"
echo "${file/.txt/.md}"

11.5 Default Values

echo "${name:-guest}"
: "${port:=8080}"

12. Processes and Jobs

12.1 Foreground and Background

sleep 100
sleep 100 &

12.2 Job Control

jobs
fg %1
bg %1
kill %1

12.3 Process Inspection

ps aux
ps -ef
pgrep ssh
pidof bash

12.4 Kill Processes

kill 1234
kill -9 1234
pkill firefox
killall nc

12.5 nohup and disown

nohup long_task.sh > task.log 2>&1 &
disown

13. Permissions and Ownership

13.1 Permission Model

-rwxr-x---

Linux permissions are split across user, group, and others.

13.2 chmod

chmod 644 file.txt
chmod 755 script.sh
chmod +x script.sh
chmod -R 750 project
  • 4 = read
  • 2 = write
  • 1 = execute
  • 7 = rwx
  • 6 = rw-
  • 5 = r-x
  • 4 = r--

13.3 chown and chgrp

chown user file.txt
chown user:group file.txt
chown -R user:group project
chgrp developers script.sh

13.4 umask

umask
umask 022

14. Networking from Bash

14.1 Connectivity Tests

ping -c 1 8.8.8.8
curl -I https://example.com
wget -qO- https://example.com

14.2 Socket Checks

ss -lnt
ss -lun
netstat -tulnp
lsof -i :80

14.3 Bash TCP Client Trick

exec 3<>/dev/tcp/example.com/80
echo -e "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n" >&3
cat <&3

14.4 Port Scan Loop

for port in 22 80 443 445 8080; do
  timeout 1 bash -c "echo >/dev/tcp/10.10.10.10/$port" 2>/dev/null && echo "Port $port open" || echo "Port $port closed"
done

14.5 Download and Execute Carefully

curl -O http://server/file
wget http://server/file -O tool.sh
chmod +x tool.sh
./tool.sh

In labs, verify what is being downloaded before execution.


15. Bash Scripting Workflow

15.1 Shebang

#!/usr/bin/env bash

15.2 First Script

#!/usr/bin/env bash

echo "Hello, Bash"
chmod +x hello.sh
./hello.sh

15.3 Positional Arguments

#!/usr/bin/env bash

echo "Script: $0"
echo "Arg1: $1"
echo "Arg2: $2"
echo "Count: $#"

15.4 Safe Script Template

#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'

main() {
  echo "Safe Bash template"
}

main "$@"
  • set -e stops on command failure.
  • set -u errors on unset variables.
  • set -o pipefail fails a pipeline if any command fails.
  • IFS=$'\n\t' reduces common word-splitting problems.

15.5 Example: Host Reachability Script

#!/usr/bin/env bash
set -euo pipefail

while IFS= read -r host; do
  if ping -c 1 -W 1 "$host" >/dev/null 2>&1; then
    echo "[+] $host is up"
  else
    echo "[-] $host is down"
  fi
done < hosts.txt

15.6 Example: Simple Recon Wrapper

#!/usr/bin/env bash
set -euo pipefail

target="${1:-}"
[ -z "$target" ] && { echo "Usage: $0 <target>"; exit 1; }

mkdir -p recon
host "$target" | tee recon/dns.txt
whois "$target" | tee recon/whois.txt

16. Debugging and Safety

16.1 Debug Mode

bash -x script.sh
set -x
set +x

16.2 Syntax Check

bash -n script.sh

16.3 Common Safety Rules

  • Quote variables unless deliberate word splitting is needed.
  • Prefer [[ ... ]] over [ ... ] in Bash scripts.
  • Use read -r to avoid backslash mangling.
  • Use rm -i or explicit paths for destructive actions.
  • Avoid parsing ls output in scripts.
  • Test scripts with filenames containing spaces.
  • Use shellcheck for linting.

16.4 ShellCheck

shellcheck script.sh

16.5 Common Pitfalls

Unquoted variables:

rm -rf $dir
rm -rf -- "$dir"

Bad line reading:

for line in $(cat file.txt); do
  echo "$line"
done

Good line reading:

while IFS= read -r line; do
  echo "$line"
done < file.txt

17. Useful One-Liners

17.1 File and Directory

find . -type f | wc -l
find . -maxdepth 1 -type d
du -sh *
ls -lahS

17.2 Users and System

cut -d: -f1 /etc/passwd
id
uname -a
hostnamectl

17.3 Logs

grep -i error /var/log/syslog | tail -n 20
journalctl -xe
journalctl -u ssh

17.4 Networking

ip a
ip r
ss -tulpn
arp -a

17.5 Hashing and Encoding

sha256sum file
md5sum file
base64 file
base64 -d encoded.txt

17.6 Loop Through Targets

for ip in $(seq 1 10); do
  ping -c 1 192.168.1.$ip >/dev/null && echo "192.168.1.$ip up"
done

18. Cheat Sheet

18.1 Most Useful Patterns

name="value"
echo "$name"
if [[ -f file ]]; then echo yes; fi
for x in a b c; do echo "$x"; done
while IFS= read -r line; do echo "$line"; done < file.txt
f(){ local x="$1"; echo "$x"; }
set -euo pipefail
IFS=$'\n\t'

18.2 Redirection Map

>      stdout overwrite
>>     stdout append
2>     stderr overwrite
2>>    stderr append
<      stdin from file
<<     heredoc
<<<    herestring
|      pipe stdout to stdin

18.3 Test Quick Reference

[[ -f file ]]
[[ -d dir ]]
[[ -z "$x" ]]
[[ -n "$x" ]]
[[ "$a" == "$b" ]]
[[ "$n" -gt 10 ]]

18.4 Script Starter

#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'

main() {
  :
}

main "$@"

19. Final Quick Reference Table

Topic Most Important Commands / Patterns
Navigation pwd, cd, ls -lah
Files cp, mv, rm, find, cat, less
Redirection >, >>, 2>, &>, <, <<, <<<
Text grep, cut, sort, uniq, sed, awk, wc
Variables name="x", export VAR=value, echo "$VAR"
Tests [[ -f file ]], [[ -z "$x" ]], [[ "$n" -gt 5 ]]
Loops for, while, until
Functions f(){ ...; }, local var=value
Safety set -euo pipefail, read -r, quote variables
Debugging bash -x, bash -n, shellcheck

← Linux top ↑