# Bash One-Liners We Actually Use

URL: https://www.devopsness.com/blog/bash-one-liners-we-actually-use
Author: Kiril Urbonas
Published: 2026-05-04
Updated: 2026-10-31
Categories: Linux
Tags: Bash, Shell, Linux, Ops, One Liners

Summary: A curated list of shell one-liners that earn their place in real ops work: the ones we reach for weekly, not the trick-shot variety.

---
# Bash One-Liners We Actually Use

The bash one-liners we actually use are boring on purpose: `du -sh | sort -h` when a disk fills, `find -mtime` for old files, `ps --sort` for memory hogs, `ss -tlnp` for ports, `journalctl --since` for log windows, `jq` for JSON, and `curl -w` for quick HTTP checks. Each solves a problem that recurs weekly. Nothing here is exotic.

> [!VERIFIED]
> GNU Coreutils 9.12 (`du`, `sort`, `date`), jq 1.8, iproute2 `ss` and systemd `journalctl`, against the gnu.org Coreutils manual, the jqlang.org manual, the man7.org man pages and the curl man page. Checked October 2026.

## Find what's eating disk

```bash
$ sudo du -sh /var/* 2>/dev/null | sort -h
```

Sums up sizes of immediate subdirectories of `/var` (or any directory), sorted by size. `-h` for human-readable; `sort -h` understands the suffixes. Always the first thing I run when a disk-full alert fires. Then I drill into the biggest one with the same pattern.

A faster alternative when the directory is huge:

```bash
$ sudo ncdu /var
```

If `ncdu` is installed, it's the right tool: interactive and navigable, so you drill down without re-running `du` at every level.

## Find files older than N days

```bash
$ find /var/log -type f -mtime +30 -size +10M
```

Files older than 30 days and bigger than 10MB. Adjust thresholds. Combine with `-delete` once you trust it:

```bash
$ find /var/log -type f -mtime +30 -size +10M -delete
```

## Top processes by memory

```bash
$ ps aux --sort=-%mem | head
```

Top entries by memory. Same flag with `-%cpu` for CPU. Old but solid, and present in most Linux images. `--sort` requires GNU procps (Linux), not BSD `ps`, and minimal BusyBox images lack it.

For sustained monitoring, `top -o %MEM` is interactive and lets you re-sort.

## Watch a metric over time

```bash
$ watch -n 1 'kubectl get pods -A | grep -v Running'
```

Re-runs the inner command every second; shows you what's NOT running. Useful for watching a deploy progress, or for catching a pod that's flapping. `-n 1` is the interval; `-d` (highlight differences) is nice when the output is long.

## Filter logs by time window

```bash
$ journalctl -u myservice --since "10 min ago" --until "5 min ago"
```

journald is the right tool for systemd-managed services. The time arguments are flexible: `"2026-04-29 14:00"`, `"yesterday"`, `"1 hour ago"`. The `--until` flank narrows the window. Retention, vacuuming and persistent storage are covered in our guide to [journald log management on Linux](/blog/journald-log-management-linux).

For grepping inside that window:

```bash
$ journalctl -u myservice --since "10 min ago" | grep -i error
```

## Pretty-print JSON

```bash
$ curl -s https://api.example.com/v1/things | jq .
```

`jq .` reads JSON on stdin and emits it pretty-printed. The `.` is the identity filter. `jq` is the right tool for any JSON wrangling beyond reading; learn it.

A common variant: extract a field across an array:

```bash
$ curl -s https://api.example.com/v1/things | jq -r '.items[].name'
```

`-r` strips quotes from string output. `.items[].name` iterates and pulls the name.

## Find which process has a file open

```bash
$ sudo lsof | grep /path/to/file
```

Useful for "I can't unmount this disk, what's still holding it?" or "what process opened this socket?" `lsof` is slow but exhaustive. For fast process-specific lookup:

```bash
$ sudo lsof -p 12345
```

Lists all files (including network sockets) open by PID 12345.

## What's listening on a port

```bash
$ sudo ss -tlnp | grep :443
```

`ss`, not `netstat`, which ships in the older net-tools package that many distributions no longer install by default. `-t` for TCP, `-l` for listening, `-n` for numeric ports, `-p` to show the process. Tells you exactly which process is listening on 443.

For the reverse direction, what a process is connected to:

```bash
$ sudo ss -tnp state established | grep -- 'pid=12345'
```

## Tail multiple logs at once

```bash
$ sudo tail -f /var/log/syslog /var/log/nginx/access.log
```

Multiple files, single follow. Prefixes each line with the source file (when alternating). For Kubernetes:

```bash
$ kubectl logs -f -l app=myservice --all-containers --max-log-requests=20 --prefix
```

Tails logs from all pods matching `app=myservice`, prefixed with pod name. The `--prefix` is the part most people miss.

## Search for a string across many files

```bash
$ grep -rIn 'TODO' --include='*.ts' .
```

`-r` recursive, `-I` skip binary files, `-n` line numbers, `--include` filter by glob. Faster than naive `grep -r` because it skips binaries.

For better defaults on a codebase, `ripgrep` (`rg`) is what I actually use:

```bash
$ rg -n TODO -t ts
```

Same result; faster; respects `.gitignore`. Install `ripgrep` everywhere you do dev work.

## Replace text across many files

```bash
$ find . -name '*.md' -type f -exec sed -i.bak 's/oldterm/newterm/g' {} +
```

`-i.bak` makes backups and works on both GNU and BSD sed; a bare `-i` on macOS needs an explicit empty suffix, `-i ''`. The `{} +` form is faster than `\;` (one sed invocation for many files).

For complex multi-pattern edits, write a small Python script instead. sed-with-regex starts feeling fragile past simple substitutions.

## Quick HTTP test from the shell

```bash
$ curl -sS -o /dev/null -w "%{http_code} %{time_total}s\n" https://api.example.com/health
```

Output: status code + time. Run in a loop for crude latency check:

```bash
$ for i in {1..10}; do
  curl -sS -o /dev/null -w "%{http_code} %{time_total}s\n" https://api.example.com/health
  sleep 1
done
```

Cheap "is this endpoint slow right now?" probe.

## Decode base64 quickly

```bash
$ echo "aGVsbG8=" | base64 -d
```

Two-way: `base64` encodes, `base64 -d` decodes. Inevitable when dealing with Kubernetes Secrets (which are base64-encoded by convention) or JWT tokens.

For JWTs specifically, split on `.` and decode the middle part:

```bash
$ TOKEN="eyJ...long.token...sig"
$ echo "$TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null | jq .
```

Useful for "what's actually in this JWT?" debugging. JWT segments are unpadded base64url, so `base64 -d` may warn; the payload usually still prints.

## Generate a strong random secret

```bash
$ openssl rand -hex 32
```

64-char hex string. Good for: API keys, signing secrets, anything where you want cryptographic randomness. `-base64` for base64 output.

```bash
$ openssl rand -base64 24
```

## SSH and run a command without a TTY

```bash
$ ssh prod 'df -h | grep -E "^/dev"'
```

Single quotes prevent local shell from expanding the command. Useful for cron-style remote checks.

## Format a date or duration in shell

```bash
$ date -u +"%Y-%m-%dT%H:%M:%SZ"      # ISO 8601 UTC
$ date -u +%s                          # Epoch seconds
$ date -u -d "@1714564800"             # Convert epoch back (GNU date)
```

Date math:

```bash
$ date -u -d "yesterday" +"%Y-%m-%d"
$ date -u -d "now - 1 hour" +"%H:%M"
```

On macOS, `gdate` (from `brew install coreutils`) is the GNU equivalent. Pure macOS `date` has different syntax.

## What I never use as a one-liner

Some patterns I see in "bash tricks" posts that I rarely or never write inline:

- **Multi-line `awk` programs.** Once awk gets past 2-3 actions, it's a script file, not a one-liner. Our [first bash script tutorial](/blog/bash-scripting-tutorial-first-script) covers the jump from one-liner to script.
- **Bash regex backreferences.** Too fragile. Use a real language.
- **`xargs -P` for parallelism.** Works but `parallel` or a small Python script is clearer.
- **Recursive `find -exec rm` with complex predicates.** Cleanup with this level of complexity should be a reviewed script, not a one-liner I type at 2am.

The principle: a one-liner you'd be comfortable typing fresh at 2am. If you'd want to read it carefully first, it's not really a one-liner anymore.

## Questions people ask

### How do I find what is using disk space on Linux?

Run `sudo du -sh /var/* 2>/dev/null | sort -h` to list the size of each subdirectory, largest last, then repeat the same command one level deeper on the biggest entry. `sort -h` understands the K, M and G suffixes that `du -h` prints.

### How do I see which process is listening on a port?

Run `sudo ss -tlnp | grep :443`, replacing 443 with your port. `-t` limits output to TCP, `-l` to listening sockets, `-n` keeps ports numeric, and `-p` shows the owning process and PID, which needs root for other users' processes. `ss` replaces `netstat` from the older net-tools package.

### How do I safely delete old log files with find?

Run the `find` command without `-delete` first, for example `find /var/log -type f -mtime +30 -size +10M`, and read the list. Only when it shows exactly what you expect, append `-delete`. `-mtime +30` means modified more than 30 days ago. For journald logs, use `journalctl --vacuum-time` instead of deleting files by hand.

## What I'd tell a team starting

**ShellCheck even on one-liners.** `shellcheck -` accepts stdin. Quick sanity check before running something destructive.

**Always dry-run destructive operations.** Run the `find` without `-delete` first; eyeball; then add `-delete`.

**`ss` not `netstat`. `ip` not `ifconfig`. `rg` not `grep -r`.** Modern tools are faster and clearer.

**Save the patterns that work.** Keep a `~/.shell-notes.md` of one-liners that solved real problems. Future-you will thank you.

These aren't impressive. They're the patterns that survive being typed weekly without thinking. The exotic stuff gets retired; these stay.

## Sources

- [GNU Coreutils manual: du invocation](https://www.gnu.org/software/coreutils/manual/html_node/du-invocation.html)
- [ss(8) Linux manual page (iproute2)](https://man7.org/linux/man-pages/man8/ss.8.html)
- [jq 1.8 Manual](https://jqlang.org/manual/)
- [curl man page (including --write-out)](https://curl.se/docs/manpage.html)

