Bash is the default shell on most Linux systems. You use it every time you open a terminal. Knowing the basics means you can automate repetitive tasks and chain tools together.
Use $() to capture command output into a variable. This is called command substitution.
Pipes and Redirection
Pipes connect commands. Redirection sends output to files.
ls -la | grep ".txt"# pipe ls into grep to filtercat file.txt | sort | uniq # sort and deduplicatecommand > output.txt # write stdout to file (overwrite)command >> output.txt # append stdout to filecommand 2> errors.txt # write stderr to filecommand 2>/dev/null # throw away errors
Piping is how you build data pipelines from small tools. grep, sort, cut, awk, and sed are all designed to be combined this way.
Conditionals
if[ condition ];then# do somethingelif[ other_condition ];then# do something elseelse# fallbackfi# Common conditions[ -f file.txt ]# file exists[ -d /tmp ]# directory exists[$x -eq 5]# equals[$x -gt 5]# greater than[ -z "$var"]# variable is empty
Loops
# For loop over a listfor ip in 192.168.1.1 192.168.1.2 192.168.1.3;do ping -c 1$ipdone# For loop over a rangefor i in {1..10};doecho$idone# While loopwhile[ condition ];do# do somethingdone
Useful One-Liners
# Search for a string across all files in a directorygrep -r "password" /var/www/
# Find files modified in the last 24 hoursfind / -mtime -1 2>/dev/null
# Extract IPs from a log filegrep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' logfile.txt
# Count occurrences of each unique linesort file.txt | uniq -c | sort -rn
# Watch a file grow in real timetail -f /var/log/auth.log
Writing a Script
#!/bin/bash
# This line tells the OS to use bash to run this scriptecho"Starting script..."for target in "$@";do# $@ = all arguments passed to scriptecho"Scanning $target" ping -c 1"$target" > /dev/null &&echo"$target is up"done
A script that keeps going after an error does damage quietly. Make it stop.
#!/bin/bash
set -euo pipefail
# -e exit on the first failed command# -u treat an unset variable as an error, not as empty text# -o pipefail a pipeline fails if any stage fails, not only the last one
Quote every variable. An unquoted variable splits on spaces and expands wildcards like *. This is the most common bash bug there is.
file="my notes.txt"cat $file# runs: cat my notes.txt -> two files, both missingcat "$file"# runs: cat "my notes.txt" -> correct
Every command returns an exit code. Zero is success. Anything else is failure. Chain on it.
grep -q "root" /etc/passwd &&echo"found"||echo"missing"some_command;echo"exit code was $?"
Run shellcheck on every script before you trust it. It catches quoting mistakes, unset variables, and wrong test syntax that bash itself never warns you about.
shellcheck script.sh
The Text Toolkit
Most CTF work is text processing. Learn these five and you stop writing Python for jobs a one-liner does.
cut -d':' -f1 /etc/passwd # column 1, split on ':'awk -F: '{print $1, $7}' /etc/passwd # columns 1 and 7sed 's/old/new/g' file.txt # replace every 'old' with 'new'sort -u file.txt # sort and drop duplicatestr 'a-z''A-Z' < file.txt # translate characters# combined: the top talkers in a web logawk '{print $1}' access.log | sort | uniq -c | sort -rn | head
Two glue tools you will use every day:
find / -name "*.conf" 2>/dev/null | xargs grep -l "password"# run a command on every resultnmap -sV 10.10.10.5 | tee scan.txt # see the output AND save it
These are not script commands. They are habits that save minutes every hour.
# Ctrl-R search your history backwards as you typehistory| grep nmap # find that command you ran an hour agosudo !! # rerun the last command as rootcd - # jump back to the previous directory
Your history is saved to ~/.bash_history. On a CTF box, it is the first place to look for credentials that were typed into commands.
In CTF Environments
Bash is the glue that holds CTF tooling together. You rarely use one tool in isolation — you pipe output between them.
Extracting a flag from tool output:
# nmap scan, pull out open ports onlynmap -p- 10.10.10.5 | grep "open"| cut -d'/' -f1
# grab all URLs from a page sourcecurl -s http://target.htb | grep -oP 'href="\K[^"]+'# extract flag-shaped strings from a binarystrings challenge | grep -E 'flag\{[^}]+\}'# decode base64 output from a serviceecho"aGVsbG8gd29ybGQ="| base64 -d
Automating a brute force loop:
# try passwords from a wordlist against a login endpointwhileIFS=read -r pass;doresult=$(curl -s -X POST http://target.htb/login \
-d "user=admin&pass=$pass")ifecho"$result"| grep -q "Welcome";thenecho"Found: $pass"breakfidone < /usr/share/wordlists/rockyou.txt
Port knocking / sequential connection script:
for port in 12345678 9012;do nmap -Pn --host-timeout 100 --max-retries 0 -p $port target.htb
done
Processing nmap XML output:
nmap -oX scan.xml target.htb
# extract just the open port numbersgrep 'state="open"' scan.xml | grep -oP 'portid="\K[0-9]+'
Using AI
AI is genuinely useful for Bash — not because it writes your scripts for you, but because it accelerates the parts that are slow.
Where it helps:
Explaining unfamiliar commands: Paste a one-liner you found in a writeup. Ask what each part does. Faster than reading five man pages.
Generating boilerplate: “Write a bash script that takes a wordlist and tries each word as a password against this curl command.” Use it as a starting point, not a final answer.
Debugging: Paste the script and the error. AI is good at spotting quoting issues, off-by-one errors, and wrong flags.
Regex help:grep -oP regex is finicky. Describe what you want to extract and let AI draft the pattern.
Converting tool output: “I have nmap output in this format. Write a bash one-liner to extract just the open ports.” This is mechanical work — offload it.
Where it fails:
It will confidently produce scripts that do not work. Always test.
It does not know your specific target’s behavior. The logic has to come from you.
Complex pipelines with process substitution and edge cases need manual review.
Treat AI output as a draft. Read it, understand it, then run it.
How the Club Uses This
TODO: Add examples of scripts the club has written for CTF automation, competition tooling, or demo exercises.