datarekha

Productivity: aliases, history, xargs

Master the habits that make terminal power users fast: history navigation, aliases, command chaining, xargs, and line-editing shortcuts.

8 min read Intermediate Command Line Lesson 14 of 14

What you'll learn

  • Navigate and reuse shell history with !!, !$, and Ctrl+R
  • Create and persist aliases to shrink repetitive commands
  • Use xargs to pipe data as arguments, safely handling tricky filenames

Before you start

The last lesson handed you scripts for the sequences you run over and over. This one is about the other half of the day — the live, interactive typing — and it answers the question you have probably had since the very first lesson: how do the pros move so fast? Watch someone who lives in the terminal and you will notice they rarely retype anything. They summon previous commands instantly, abbreviate long invocations to two characters, and compose small tools into precise one-liners. None of this is magic — it is a handful of habits layered on three ideas:

  • Recall — stop retyping things you have already typed
  • Alias — name things you type often
  • Compose — wire small commands together

Each section below adds one layer.


History: stop retyping commands

Your shell keeps a log of everything you run. The history command prints it:

history
 498  git status
 499  npm run build
 500  git add -A
 501  git commit -m "fix layout"

Re-run the last command with !!

!! expands to the full previous command. The classic use-case is forgetting sudo:

apt install ripgrep
# Permission denied
sudo !!
# Expands to: sudo apt install ripgrep

Reuse the last argument with !$

!$ expands to the last word of the previous command — often a filename or path.

mkdir -p src/components/Button
cd !$
# Expands to: cd src/components/Button

Ctrl+R — reverse-search (the big one)

Press Ctrl+R and start typing any fragment of a past command. The shell searches backward through history and shows the most recent match. Keep pressing Ctrl+R to cycle through older matches. Press Enter to run or any arrow key to land it on the prompt for editing.

(reverse-i-search)`docker': docker compose up -d

This single shortcut replaces memorising history numbers and is the move that most visibly separates fast terminal users from slow ones.


Aliases: name the things you type often

An alias is a short name that expands to a longer command before the shell runs it.

alias ll='ls -lah'
alias g=git
alias ..='cd ..'
alias gs='git status'

Run an alias exactly like a real command:

ll
# Same as: ls -lah

Persisting aliases

Aliases defined at the prompt vanish when the terminal closes. To keep them, add them to your shell’s startup file:

  • Zsh (default on macOS): ~/.zshrc
  • Bash: ~/.bashrc or ~/.bash_profile
# ~/.zshrc
alias ll='ls -lah'
alias g=git
alias gs='git status'
alias gc='git commit -m'

After editing, reload the file without restarting:

source ~/.zshrc

Command chaining: control what runs next

The shell uses a command’s exit status (0 = success, anything else = failure) to decide whether to run the next one.

OperatorMeaning
&&Run next only if previous succeeded
||Run next only if previous failed
;Always run next, regardless
npm run build && npm run deploy
# deploy only runs if build exits 0

mkdir dist || echo "dist already exists"
# echo only runs if mkdir fails

git pull ; git status
# status runs no matter what

cd - — toggle between two directories

cd - switches back to whichever directory you were in before the last cd. Run it again and you return. It is the quickest way to shuttle between two locations.

cd ~/projects/api
cd ~/projects/web
cd -   # back to ~/projects/api
cd -   # back to ~/projects/web

xargs: turn stdin into arguments

Pipes send one command’s output to another command’s stdin. But many commands (like rm, cp, open) do not read from stdin — they expect arguments.

xargs bridges that gap: it reads lines from stdin and passes them as arguments to a command.

find . -name "*.tmp" | xargs rm

find prints a list of paths; xargs batches them and runs rm path1 path2 path3 ... rather than invoking rm once per file.

Placing arguments with -I {}

By default xargs appends arguments at the end. Use -I {} to control exactly where they land:

find . -name "*.log" | xargs -I {} mv {} logs/archived/

{} is replaced by each input item in turn.

Safe filenames with -print0 and -0

Filenames can contain spaces or newlines. Plain newline-splitting breaks in those cases. The safe pairing is find -print0 (null-terminate output) with xargs -0 (split on null bytes instead of newlines):

find . -name "*.tmp" -print0 | xargs -0 rm

This handles filenames like my report (draft).tmp correctly.


Line-editing shortcuts

These work in any readline-based shell (Bash, Zsh) and save reaching for the mouse:

ShortcutAction
Ctrl+AMove cursor to start of line
Ctrl+EMove cursor to end of line
Ctrl+WDelete the word to the left
Ctrl+UCut everything to the left of the cursor
Ctrl+KCut everything to the right of the cursor
Ctrl+YPaste what was cut
Ctrl+LClear the screen (keeps current command)

Persistent sessions: tmux and screen

If you SSH into a remote server, your session dies the moment the connection drops. tmux and screen are terminal multiplexers that keep sessions alive on the server — you can detach, close your laptop, reconnect hours later, and find everything exactly as you left it. Running tmux is worth learning as a separate topic once the basics above are comfortable.

In one breath

Speed in the terminal is three habits. Recall: stop retyping — !! re-runs the last command (sudo !! after a permission error), !$ grabs its last argument, and Ctrl+R reverse-searches your whole history by any fragment (the single biggest win). Alias: name what you type often (alias gs='git status') and persist it in ~/.zshrc/~/.bashrc — but know an alias can shadow a real command, so type name when unsure. Compose: chain on success with &&, on failure with ||, always with ;; and use xargs to feed a list into commands that take arguments not stdin (find ... | xargs rm), reaching for find -print0 | xargs -0 so spaces in filenames never bite. Layer in the readline shortcuts (Ctrl+A/E/W/U/K) and tmux for sessions that survive a dropped SSH.

Practice

Before the quiz, speed-run three everyday moments: (a) you ran apt install ripgrep and got “permission denied” — what two characters re-run it as root? (b) you want to delete every .tmp file find can locate, and some have spaces in their names — write the safe pipeline. (c) you find yourself typing git status thirty times a day — what one line in ~/.zshrc fixes that forever, and what command applies it to the shell you are in right now?

Quick check

0/3
Q1You just ran `git push origin main`. You want to run the same command again. Which is the shortest correct way?
Q2You add `alias rm='rm -i'` to your ~/.zshrc so rm always prompts before deleting. A colleague hands you a script that calls `rm` and expects it to run non-interactively. What problem might you hit?
Q3A teammate gives you this command: `find /var/log -name '*.gz' | xargs rm`. You notice some log filenames contain spaces. What is the safest replacement?

A question to carry forward

Look back at the distance you have come. The first lesson of this section opened with a blinking cursor and the bare question, what even is the shell? You can now answer it cold — and you can move around a filesystem, reshape it, read any file, search and slice text into reports, control permissions and processes, reach across the network into remote machines and live APIs, freeze your workflows into scripts, and fly through all of it with the habits in this lesson. The terminal is no longer a place you copy-and-paste into nervously; it is an instrument you play.

So the final question is not “what comes next in this course” — there is no next; you have finished it. The real question is the one only you can answer: now that the machine will do exactly, precisely what you tell it, what will you tell it to do? Point this at your own real work — the dataset that needs wrangling, the server that needs watching, the hundred-file chore you have been dreading — and the fluency stops being lesson material and becomes yours for good. That was the whole point. Go build something.

Sign in to track your progress

Completed lessons, your XP, level, and streak save to your account — it's free and takes a few seconds.

Related lessons

Explore further

Skip to content