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:
- Reads the input.
- Expands variables, wildcards, and substitutions.
- Resolves whether the command is a builtin, function, alias, or executable.
- Executes it.
- 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 descriptor0stdout= file descriptor1stderr= file descriptor2
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= read2= write1= execute7= rwx6= rw-5= r-x4= 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 -estops on command failure.set -uerrors on unset variables.set -o pipefailfails 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 -rto avoid backslash mangling. - Use
rm -ior explicit paths for destructive actions. - Avoid parsing
lsoutput in scripts. - Test scripts with filenames containing spaces.
- Use
shellcheckfor 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 |