Shell builtins cheat sheet
The most useful shell builtins commands on one printable page, every line checked by running it.
alias Define a short name that the shell replaces with a longer command line, or list the aliases already defined.
shopt -s expand_aliases alias lt='ls -t' lt data | head -n 3- Define and use an alias output
alias ll='ls -l' la='ls -A' gs='git status' alias- List the defined aliases output
errors() { grep -c "ERROR" "$@"; } errors logs/app.log errors -h logs/app.log logs/error.log- Use a function when you need arguments output
shopt -s expand_aliases alias ls='ls -F' ls scripts \ls scripts command ls scripts- Bypass an alias for one command output
command Run a command while skipping functions and aliases of the same name, or check whether a command exists with -v.
for tool in jq curl kubectl; do if command -v "$tool" >/dev/null 2>&1; then echo "$tool: found at $(command -v "$tool")" else echo "$tool: not installed" fi done- Check whether a program is installed output
grep() { command grep --color=never -n "$@"; } grep TODO notes.txt src/app.py- Wrap a command in a function of the same name output
ls() { echo "(ls is overridden)"; } ls scripts command ls scripts- Bypass a function or alias for one call output
declare Create variables with attributes (array, associative array, integer, read-only, exported), or show how variables are defined.
name="Alice Moreau" empty="" list=(one "two words" three) declare -p name empty list- Inspect a variable exactly with -p output
declare -A port=([web]=80 [db]=5432) port[cache]=6379 for k in "${!port[@]}"; do echo "$k -> ${port[$k]}"; done | sort- Create an associative array with -A output
add_item() { declare -n list=$1 list+=("$2") } fruits=(apple) add_item fruits banana add_item fruits cherry declare -p fruits- Refer to another variable by name with -n output
count=1 f() { declare count=99; echo "inside: $count"; } g() { declare -g count=42; } f; echo "after f: $count" g; echo "after g: $count"- declare inside a function makes a local variable output
eval Join the arguments into a string and run it as shell code, with a second round of parsing and expansion.
bash greet-unsafe.sh 'Alice' bash greet-unsafe.sh 'Alice; touch HACKED; ls H*'- Why eval is dangerous output
args=(-c -i) pattern='error' args+=(-- "$pattern" "logs/app.log") grep "${args[@]}"- Build commands with an array instead output
db_host=db01; web_host=web01 role=db var="${role}_host" echo "unsafe: $(eval "echo \$$var")" echo "safe: ${!var}"- Read a variable whose name is in another variable output
name='Alice; touch HACKED' eval "echo Hello, $(printf '%q' "$name")" ls HACKED- Quote safely with %q when you must generate code output
exec Replace the shell with another program, or, with only redirections, change where the shell's own input and output go.
echo "shell pid: $$" exec bash -c 'echo "new program pid: $$"' echo "this line never runs"- Replace the shell with another program output
bash run-greet.sh Alice echo "wrapper exit status: $?"- End a wrapper script with exec output
bash job.sh echo "--- run.log:" cat run.log- Send the rest of a script's output to a log file output
exec 3>&1 exec >capture.txt echo "written to the file" exec 1>&3 3>&- echo "back on the terminal" echo "file contains: $(cat capture.txt)"- Redirect temporarily and restore the original output output
export Mark shell variables (or bash functions) to be passed to every program the shell starts.
COLOR=blue bash -c 'echo "child sees COLOR=[$COLOR]"' export COLOR bash -c 'echo "child sees COLOR=[$COLOR]"'- Make a variable visible to child processes output
export API_URL=http://localhost:8080 RETRIES=3 env | grep -E '^(API_URL|RETRIES)='- Set and export in one step output
TZ=Asia/Tokyo date +%H:%M-%Z date +%H:%M-%Z echo "TZ in this shell: [${TZ-unset}]"- Set a variable for a single command output
mkdir -p ~/bin printf '#!/bin/sh\necho "hello from ~/bin"\n' > ~/bin/hello chmod +x ~/bin/hello export PATH="$HOME/bin:$PATH" hello echo "$PATH" | tr : '\n' | head -n 3- Add a directory to PATH output
false Do nothing and exit with status 1 (failure).
getopts Parse short command-line options such as -v and -o FILE in a script, one option per call, inside a while loop.
chmod +x backup.sh ./backup.sh -v -o /tmp/out data logs ./backup.sh data- A complete script with getopts output
set -- -v -o out.txt input.csv while getopts 'vo:' opt; do echo "got -$opt, OPTIND now $OPTIND"; done shift $((OPTIND - 1)) echo "remaining: $*"- Watch OPTIND advance output
f() { local OPTIND opt while getopts 'q' opt; do echo " option -$opt"; done shift $((OPTIND - 1)); echo " args: $*" } echo "first call:"; f -q one echo "second call:"; f -q two- Reset OPTIND when using getopts in a function output
local Declare variables inside a function that disappear when it returns, leaving any global of the same name untouched.
name="global" without() { name="changed by without"; } with() { local name="changed by with"; echo "inside with: $name"; } with; echo "after with: $name" without; echo "after without: $name"- Keep a function's variables to itself output
show() { echo "show sees level=$level"; } outer() { local level=outer; show; } level=global outer show- Locals are visible to called functions output
bad() { local out=$(grep -c CRITICAL logs/app.log); echo "status after local=: $?"; } good() { local out; out=$(grep -c CRITICAL logs/app.log); echo "status after split: $?"; } bad; good- local hides the exit status of command substitution output
mapfile Read lines from standard input into an indexed array, one line per element (also called readarray).
mapfile -t tasks < todo.txt echo "${#tasks[@]} tasks" echo "first: ${tasks[0]}" echo "last: ${tasks[-1]}"- Read a file into an array output
mapfile -t errors < <(grep ERROR logs/app.log) echo "found ${#errors[@]} errors" printf ' > %s\n' "${errors[@]}"- Capture command output with process substitution output
mapfile -t -s 1 -n 3 rows < data/users.csv printf '%s\n' "${rows[@]}"- Skip a header and limit the count with -s and -n output
touch 'photos/new line.png' mapfile -t -d '' pics < <(find photos -name '*.png' -print0) echo "${#pics[@]} files" printf '<%s>\n' "${pics[@]}" | sort- Collect file names safely with -d '' output
popd Remove the top directory from the directory stack and change back to the next one.
pushd data >/dev/null pushd ../logs >/dev/null dirs -v popd popd- Return to the previous directory output
pushd /tmp >/dev/null touch scratch.$$ popd >/dev/null echo "back in $PWD"- Use popd quietly in a script output
pushd /tmp >/dev/null; pushd /etc >/dev/null; pushd /usr >/dev/null dirs -v popd +2 >/dev/null echo "after popd +2, still in $PWD:" dirs -v- Remove a specific entry with +N output
pushd Change to a directory and remember the previous one on a stack, so popd can return to it.
pushd data pwd pushd ../logs dirs -v- Change directory and remember where you were output
pushd /etc >/dev/null echo "now in $PWD" popd >/dev/null echo "back in $PWD"- Go somewhere and come back with popd output
pushd src >/dev/null pushd >/dev/null; echo "1: $PWD" pushd >/dev/null; echo "2: $PWD" pushd >/dev/null; echo "3: $PWD"- Toggle between two directories output
read Read one line from standard input and split it into shell variables.
while read -r host ip; do echo "$host is at $ip" done < data/hosts.txt- Process a file line by line output
tail -n +2 data/users.csv | head -n 3 | while IFS=, read -r id name email dept joined; do printf '%-14s %s\n' "$name" "$dept" done- Split on a different separator with IFS output
printf ' indented line \n' > in.txt read -r line < in.txt; echo "[$line]" IFS= read -r line < in.txt; echo "[$line]"- Preserve leading spaces with IFS= output
read -r count < <(grep -c . todo.txt) echo "count=$count" read -r first rest <<< "a b c" echo "first=$first rest=$rest"- Read command output into variables in the current shell output
find photos -name '*.png' -print0 | sort -z | while IFS= read -r -d '' f; do echo "file: $f" done- Read NUL-separated names with -d '' output
set Turn shell options such as -e, -u, -x and pipefail on or off, and replace the positional parameters.
set -e echo "start" ls missing-file echo "never printed"- Stop a script at the first failing command with -e output
set -u backup_dir=/tmp/backups echo "cleaning ${backup_dri}" echo "not reached"- Catch typos in variable names with -u output
grep ERROR missing.log | wc -l; echo "status without pipefail: $?" set -o pipefail grep ERROR missing.log | wc -l; echo "status with pipefail: $?"- Make a pipeline fail when any part fails output
set -x name="file with spaces.txt" wc -l "$name" set +x echo "tracing is off"- Trace each command before it runs with -x output
set -- alpha "beta gamma" delta echo "count: $#" printf '[%s]\n' "$@"- Replace the positional parameters output
shift Drop the first N positional parameters ($1, $2, ...) and renumber the rest down.
set -- alpha beta gamma echo "before: \$1=$1, $# args" shift echo "after: \$1=$1, $# args, all: $*"- Drop the first argument output
bash tool.sh count todo.txt notes.txt bash tool.sh show "file with spaces.txt"- Split off a subcommand and pass the rest through output
bash deploy.sh --env=prod -n web01 web02 bash deploy.sh -e dev web01 bash deploy.sh --dry-run -- -odd-host- Parse options by hand, including long options output
source Run the commands in a file inside the current shell, so its variables, functions and directory changes stay in effect.
source ./app.env echo "$APP_NAME listens on $APP_PORT"- Load variables from a file into the current shell output
bash setdir.sh echo "after bash: pwd=$PWD greeting=[$GREETING]" source ./setdir.sh echo "after source: pwd=$PWD greeting=[$GREETING]"- Sourcing versus running a script output
source src/util.sh log "starting backup" type die | head -n 3- Use functions from a library file output
. ./.env echo "API_URL is $API_URL" source ./.env- The portable form is a dot output
test Evaluate a condition about files, strings or integers and return 0 for true or 1 for false.
if [ -f notes.txt ]; then echo "notes.txt is a regular file"; fi test -d data && echo "data is a directory" [ -e nothing.txt ] || echo "nothing.txt does not exist"- Check that a file exists output
[ 10 = 10.0 ] && echo "= equal" || echo "= different" [ 010 -eq 10 ] && echo "-eq equal" || echo "-eq different" [[ 9 > 10 ]] && echo "[[ > ]] says 9 is greater (text order)" (( 9 > 10 )) || echo "(( > )) says 9 is smaller"- String comparison versus numeric comparison output
name="" if [ $name = "admin" ]; then echo admin; else echo "not admin"; fi if [ -n $name ]; then echo "-n says non-empty"; fi if [ -n "$name" ]; then echo "never"; else echo "quoted -n says empty"; fi- An unquoted empty variable breaks [ output
file="file with spaces.txt" [ -f $file ] || echo "[ with unquoted var: failed" [[ -f $file ]] && echo "[[ with unquoted var: works" [[ $file == *.txt ]] && echo "pattern match: ends in .txt" [[ $file =~ ^file\ (.*)\.txt$ ]] && echo "regex group: ${BASH_REMATCH[1]}"- [[ ]] does not split variables and supports patterns output
for p in notes.txt data link-to-notes scripts/greet.sh missing; do printf '%-17s' "$p" [ -e "$p" ] && printf ' exists' || printf ' missing' [ -f "$p" ] && printf ' file' [ -d "$p" ] && printf ' dir' [ -L "$p" ] && printf ' symlink' [ -x "$p" ] && printf ' executable' echo done- Distinguish files, directories and links output
trap Run a command when the shell receives a signal or exits, typically to clean up temporary files.
bash job.sh echo "exit status: $?"- Clean up a temporary file whatever happens output
bash report.sh data bash report.sh nope; echo "caller sees $?"- See the exit code inside an EXIT trap output
trap 'echo "caught SIGINT, stopping cleanly"; exit 130' INT echo "working..." kill -INT $$ echo "not reached"- Handle Ctrl-C (SIGINT) output
trap 'echo "error: status $? at line $LINENO: $BASH_COMMAND" >&2' ERR grep -q kiwi data/fruits.txt ls data > /dev/null false echo "the ERR trap does not stop the shell"- Report the failing line with an ERR trap output
true Do nothing and exit with status 0 (success).
type Show how the shell would interpret a name, as an alias, keyword, function, builtin or file on PATH.
ulimit Show or set per-process resource limits such as open files, core size and stack size.
ulimit -n- Show the open-files limit output
echo "soft: $(ulimit -Sn) hard: $(ulimit -Hn)"- Show the soft and hard limits separately output
(ulimit -n 4096; echo "inside: $(ulimit -n)") echo "outside: $(ulimit -n)"- Raise the open-files limit for one command output
echo "core limit: $(ulimit -c)" ulimit -c 0 echo "core limit now: $(ulimit -c)"- Check and disable core dumps output
umask Show or set the mask that removes permission bits from newly created files and directories.
unset Remove shell variables, array elements or functions, so they no longer exist rather than being empty.
name="Alice" unset name echo "name=[$name]" echo "${name-it is unset}"- Remove a variable output
ls() { echo "fake ls"; } ls scripts unset -f ls ls scripts- Remove a function with -f output
fruits=(apple banana cherry date) unset 'fruits[1]' echo "values: ${fruits[*]}" echo "indices: ${!fruits[*]}" echo "count: ${#fruits[@]}"- Remove one array element output
yes Print a line (y by default) over and over until killed or the reader stops reading.
From https://opscape.vip/cheatsheets/shell/ · checked 2026-10-31