Useful Bash One-Liners for Sysadmins and Developers
Short commands that save hours. Use them in the terminal, or drop them into scripts. They're grouped by task.
Find files
find . -name '*.log' -mtime +30 # older than 30 days
find . -name '*.log' -mtime +30 -delete # ...and delete them
find / -xdev -type f -size +100M -printf '%s %p\n' | sort -rn | head # 10 biggest files
find . -type f -empty # empty files
find . -type f -newer reference.txt # newer than a file
Run a command on every match (null-safe for odd filenames):
find . -name '*.jpg' -print0 | xargs -0 -r -n1 -P4 mogrify -resize 1200x
Search inside files
grep -rn "TODO" src/ # recursive, with line numbers
grep -rIl "password" /etc 2>/dev/null # only list filenames, skip binary
grep -rwi --include='*.php' "mysqli" . # whole word, case-insensitive, only PHP files
grep -v '^#' config.conf | grep -v '^$' # show a config without comments/blank lines
grep -c "ERROR" app.log # count matching lines
Log analysis
Top 10 visitors in a web access log:
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head
Count of each HTTP status code:
awk '{print $9}' access.log | sort | uniq -c | sort -rn
Most requested URLs:
awk '{print $7}' access.log | sort | uniq -c | sort -rn | head -20
Requests per hour:
awk '{print substr($4,2,14)}' access.log | uniq -c
Follow a log and only show errors, live:
tail -f app.log | grep --line-buffered -i error
Failed SSH logins by IP (Debian/Ubuntu):
sudo journalctl -u ssh --since today | grep 'Failed password' | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head
Text processing
sed -i 's/old/new/g' file.txt # replace in place
sed -i.bak 's/old/new/g' file.txt # ...and keep a .bak copy
sed -n '10,20p' file.txt # print lines 10 to 20
cut -d: -f1 /etc/passwd # first column of a delimited file
sort -u file.txt # sort and remove duplicates
awk -F, '{sum+=$3} END {print sum}' data.csv # sum column 3
column -t -s, data.csv | head # align CSV as a table
diff <(sort a.txt) <(sort b.txt) # compare two sorted outputs
comm -23 <(sort a.txt) <(sort b.txt) # lines only in a.txt
Always test a sed -i on a copy first.
Rename files in bulk
for f in *.jpeg; do mv -- "$f" "${f%.jpeg}.jpg"; done
for f in *\ *; do mv -- "$f" "${f// /_}"; done # spaces → underscores
System and processes
ps aux --sort=-%mem | head # top memory users
ps aux --sort=-%cpu | head # top CPU users
du -sh * | sort -h # sizes in the current dir, smallest first
df -h | grep -v tmpfs
watch -n 2 'df -h /' # repeat a command every 2 s
ss -tn state established | wc -l # number of established TCP connections
free -h; uptime
lsof -i -P -n | grep LISTEN # listening ports with processes
Archives and transfer
tar czf backup-$(date +%F).tar.gz /var/www # create
tar xzf backup.tar.gz -C /restore/path # extract to a directory
tar tzf backup.tar.gz | head # list contents
rsync -avh --progress /src/ user@host:/dest/ # copy, only what changed (note the trailing /)
rsync -avh --delete /src/ /backup/ # mirror, deleting extras (careful)
scp file.txt user@host:/tmp/
Network
curl -I https://example.com # headers only
curl -s -o /dev/null -w '%{http_code} %{time_total}s\n' https://example.com
curl -fsSL https://example.com/script.sh | less # inspect before running anything you download
dig +short example.com # DNS lookup
nc -zv host 443 # is a port reachable?
Generate things
openssl rand -base64 24 # random password
openssl rand -hex 16 # random hex token
date +%F_%H-%M # 2026-10-16_14-30
uuidgen
Shell shortcuts
| Keys / command | Does |
|---|---|
Ctrl+R |
search command history |
!! |
repeat the last command (sudo !! repeats with sudo) |
!$ |
last argument of the previous command |
Ctrl+A / Ctrl+E |
jump to start / end of line |
Ctrl+W |
delete the previous word |
cd - |
go back to the previous directory |
history \| grep ssh |
find an old command |
Before you run rm, sed -i or find ... -delete on real data, run the same command without the destructive part first and check what it would touch.