\documentclass[10pt,a4paper]{article} % Packages \usepackage{fancyhdr} % For header and footer \usepackage{multicol} % Allows multicols in tables \usepackage{tabularx} % Intelligent column widths \usepackage{tabulary} % Used in header and footer \usepackage{hhline} % Border under tables \usepackage{graphicx} % For images \usepackage{xcolor} % For hex colours %\usepackage[utf8x]{inputenc} % For unicode character support \usepackage[T1]{fontenc} % Without this we get weird character replacements \usepackage{colortbl} % For coloured tables \usepackage{setspace} % For line height \usepackage{lastpage} % Needed for total page number \usepackage{seqsplit} % Splits long words. %\usepackage{opensans} % Can't make this work so far. Shame. Would be lovely. \usepackage[normalem]{ulem} % For underlining links % Most of the following are not required for the majority % of cheat sheets but are needed for some symbol support. \usepackage{amsmath} % Symbols \usepackage{MnSymbol} % Symbols \usepackage{wasysym} % Symbols %\usepackage[english,german,french,spanish,italian]{babel} % Languages % Document Info \author{armk} \pdfinfo{ /Title (bash-expansions.pdf) /Creator (Cheatography) /Author (armk) /Subject (Bash expansions Cheat Sheet) } % Lengths and widths \addtolength{\textwidth}{6cm} \addtolength{\textheight}{-1cm} \addtolength{\hoffset}{-3cm} \addtolength{\voffset}{-2cm} \setlength{\tabcolsep}{0.2cm} % Space between columns \setlength{\headsep}{-12pt} % Reduce space between header and content \setlength{\headheight}{85pt} % If less, LaTeX automatically increases it \renewcommand{\footrulewidth}{0pt} % Remove footer line \renewcommand{\headrulewidth}{0pt} % Remove header line \renewcommand{\seqinsert}{\ifmmode\allowbreak\else\-\fi} % Hyphens in seqsplit % This two commands together give roughly % the right line height in the tables \renewcommand{\arraystretch}{1.3} \onehalfspacing % Commands \newcommand{\SetRowColor}[1]{\noalign{\gdef\RowColorName{#1}}\rowcolor{\RowColorName}} % Shortcut for row colour \newcommand{\mymulticolumn}[3]{\multicolumn{#1}{>{\columncolor{\RowColorName}}#2}{#3}} % For coloured multi-cols \newcolumntype{x}[1]{>{\raggedright}p{#1}} % New column types for ragged-right paragraph columns \newcommand{\tn}{\tabularnewline} % Required as custom column type in use % Font and Colours \definecolor{HeadBackground}{HTML}{333333} \definecolor{FootBackground}{HTML}{666666} \definecolor{TextColor}{HTML}{333333} \definecolor{DarkBackground}{HTML}{A3A3A3} \definecolor{LightBackground}{HTML}{F3F3F3} \renewcommand{\familydefault}{\sfdefault} \color{TextColor} % Header and Footer \pagestyle{fancy} \fancyhead{} % Set header to blank \fancyfoot{} % Set footer to blank \fancyhead[L]{ \noindent \begin{multicols}{3} \begin{tabulary}{5.8cm}{C} \SetRowColor{DarkBackground} \vspace{-7pt} {\parbox{\dimexpr\textwidth-2\fboxsep\relax}{\noindent \hspace*{-6pt}\includegraphics[width=5.8cm]{/web/www.cheatography.com/public/images/cheatography_logo.pdf}} } \end{tabulary} \columnbreak \begin{tabulary}{11cm}{L} \vspace{-2pt}\large{\bf{\textcolor{DarkBackground}{\textrm{Bash expansions Cheat Sheet}}}} \\ \normalsize{by \textcolor{DarkBackground}{armk} via \textcolor{DarkBackground}{\uline{cheatography.com/215747/cs/47805/}}} \end{tabulary} \end{multicols}} \fancyfoot[L]{ \footnotesize \noindent \begin{multicols}{3} \begin{tabulary}{5.8cm}{LL} \SetRowColor{FootBackground} \mymulticolumn{2}{p{5.377cm}}{\bf\textcolor{white}{Cheatographer}} \\ \vspace{-2pt}armk \\ \uline{cheatography.com/armk} \\ \end{tabulary} \vfill \columnbreak \begin{tabulary}{5.8cm}{L} \SetRowColor{FootBackground} \mymulticolumn{1}{p{5.377cm}}{\bf\textcolor{white}{Cheat Sheet}} \\ \vspace{-2pt}Published 16th March, 2026.\\ Updated 16th March, 2026.\\ Page {\thepage} of \pageref{LastPage}. \end{tabulary} \vfill \columnbreak \begin{tabulary}{5.8cm}{L} \SetRowColor{FootBackground} \mymulticolumn{1}{p{5.377cm}}{\bf\textcolor{white}{Sponsor}} \\ \SetRowColor{white} \vspace{-5pt} %\includegraphics[width=48px,height=48px]{dave.jpeg} Measure your website readability!\\ www.readability-score.com \end{tabulary} \end{multicols}} \begin{document} \raggedright \raggedcolumns % Set font size to small. Switch to any value % from this page to resize cheat sheet text: % www.emerson.emory.edu/services/latex/latex_169.html \footnotesize % Small font. \begin{multicols*}{2} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Official docs}} \tn % Row 0 \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{The bible (short version)} \tn \mymulticolumn{1}{x{8.4cm}}{\hspace*{6 px}\rule{2px}{6px}\hspace*{6 px}\seqsplit{https://linux.die.net/man/1/bash}} \tn % Row Count 2 (+ 2) % Row 1 \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{The bible (full version)} \tn \mymulticolumn{1}{x{8.4cm}}{\hspace*{6 px}\rule{2px}{6px}\hspace*{6 px}\seqsplit{https://www.gnu.org/software/bash/manual/bash.html}} \tn % Row Count 5 (+ 3) \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{x{3.44 cm} x{4.56 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{8.4cm}}{\bf\textcolor{white}{Parameter expansion}} \tn % Row 0 \SetRowColor{LightBackground} \$\{var{\bf{:-}}word\} & Substitute word if var is unset or null \tn % Row Count 2 (+ 2) % Row 1 \SetRowColor{white} \$\{var{\bf{:=}}word\} & Substitute and assign word to var if var is unset/null \tn % Row Count 5 (+ 3) % Row 2 \SetRowColor{LightBackground} \$\{var{\bf{:?}}word\} & Write word to stderr and exit if var is unset/null \tn % Row Count 8 (+ 3) % Row 3 \SetRowColor{white} \$\{var{\bf{:+}}word\} & Substitute word if var is set or non null \tn % Row Count 10 (+ 2) % Row 4 \SetRowColor{LightBackground} \$\{var{\bf{:offset{[}:len{]}}}\} & Expands to up to len characters of var starting at the character specified by offset. \tn % Row Count 14 (+ 4) % Row 5 \SetRowColor{white} \$\{{\bf{!}}var\} & Indirection: expands the the value of the value of var \tn % Row Count 17 (+ 3) % Row 6 \SetRowColor{LightBackground} \$\{{\bf{!}}prefix{\bf{*}}\} & Expands to the names of variables whose names begin with prefix separated by IFS{[}0{]} (as single word) \tn % Row Count 22 (+ 5) % Row 7 \SetRowColor{white} \$\{{\bf{!}}prefix{\bf{@}}\} & Same as above but as multiple words \tn % Row Count 24 (+ 2) % Row 8 \SetRowColor{LightBackground} \$\{{\bf{!}}name{\bf{{[}*{]}}}\} & Expands to the list of array indices (keys) assigned in name \tn % Row Count 27 (+ 3) % Row 9 \SetRowColor{white} \$\{{\bf{\#}}var\} & Length of var, or length of array for \$\{\#arr{[}*{]}\} \tn % Row Count 30 (+ 3) \end{tabularx} \par\addvspace{1.3em} \vfill \columnbreak \begin{tabularx}{8.4cm}{x{3.44 cm} x{4.56 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{8.4cm}}{\bf\textcolor{white}{Parameter expansion (cont)}} \tn % Row 10 \SetRowColor{LightBackground} \$\{var{\bf{\#}}word\} & Removes shortest prefix word from var. \tn % Row Count 2 (+ 2) % Row 11 \SetRowColor{white} \$\{var{\bf{\#\#}}word\} & Same as above but with longest prefix \tn % Row Count 4 (+ 2) % Row 12 \SetRowColor{LightBackground} \$\{parameter{\bf{\%}}word\} & Removes shortest suffix word from var. \tn % Row Count 6 (+ 2) % Row 13 \SetRowColor{white} \$\{parameter{\bf{\%\%}}word\} & Same as above but with longest suffix \tn % Row Count 8 (+ 2) % Row 14 \SetRowColor{LightBackground} \$\{var{\bf{/}}pattern{\bf{/}}string\} & Substitute first instance of pattern in var with string \tn % Row Count 11 (+ 3) % Row 15 \SetRowColor{white} \$\{var{\bf{//}}pattern{\bf{/}}string\} & Same as above, but all instances \tn % Row Count 13 (+ 2) % Row 16 \SetRowColor{LightBackground} \$\{var{\bf{/\#}}pattern{\bf{/}}string\} & Same as above, but pattern must be at beginning of var \tn % Row Count 16 (+ 3) % Row 17 \SetRowColor{white} \$\{var{\bf{/\%}}pattern{\bf{/}}string\} & Same as above, but pattern must be at the end of var \tn % Row Count 19 (+ 3) % Row 18 \SetRowColor{LightBackground} \$\{var{\bf{\textasciicircum{}}}pattern\} & Uppercases the first character of var if it matches pattern. Empty pattern matches all. \tn % Row Count 23 (+ 4) % Row 19 \SetRowColor{white} \$\{var{\bf{\textasciicircum{}\textasciicircum{}}}pattern\} & Uppercases every match of pattern in var \tn % Row Count 25 (+ 2) % Row 20 \SetRowColor{LightBackground} \$\{var{\bf{,}}pattern\} & Same as \$\{var\textasciicircum{}pattern\} but lowercase \tn % Row Count 27 (+ 2) % Row 21 \SetRowColor{white} \$\{var{\bf{,,}}pattern\} & Same as \$\{var\textasciicircum{}\textasciicircum{}pattern\} but lowercase \tn % Row Count 29 (+ 2) % Row 22 \SetRowColor{LightBackground} \$\{var@operator\} & Various operations, see manual. Includes case modification, length, automatic quoting and escaping, variable export, reading attributes. \tn % Row Count 36 (+ 7) \hhline{>{\arrayrulecolor{DarkBackground}}--} \SetRowColor{LightBackground} \mymulticolumn{2}{x{8.4cm}}{\{\{link="https://www.gnu.org/software/bash/manual/bash.html\#Shell-Parameter-Expansion-1"\}\}3.5.3 Shell Parameter Expansion\{\{/link\}\} \newline {\emph{word}} is subject to tilde expansion, parameter expansion, command substitution, and arithmetic expansion. {\emph{pattern}} matches according to pattern matching.} \tn \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Conditional Expressions}} \tn % Row 0 \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{if `command`} \tn \mymulticolumn{1}{x{8.4cm}}{\hspace*{6 px}\rule{2px}{6px}\hspace*{6 px}Checks for return code of `command`} \tn % Row Count 2 (+ 2) % Row 1 \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{{[} expression {]}} \tn \mymulticolumn{1}{x{8.4cm}}{\hspace*{6 px}\rule{2px}{6px}\hspace*{6 px}External tool ("test") that runs with parameters expression and returns 0 for true, 1 for false.\{\{nl\}\}Word splitting, parameter expansion and filename glob expansions occur before the test command runs: {\bf{always quote variables}} to prevent word expansion and filename expansion unless desired.} \tn % Row Count 10 (+ 8) % Row 2 \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{{[}{[} conditional {]}{]}} \tn \mymulticolumn{1}{x{8.4cm}}{\hspace*{6 px}\rule{2px}{6px}\hspace*{6 px}Internal bash builtin that runs the conditional check. Expansions are performed except word splitting and filename expansion: quoting variables is not necessary.\{\{nl\}\}Supports \textless{} and \textgreater{} as comparison operators, \&\& and || as and/or chaining operators, =\textasciitilde{} as regex matching operator} \tn % Row Count 17 (+ 7) \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{8.4cm}}{\bf\textcolor{white}{Order of expansions}} \tn % Row 0 \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{1 - Word splitting} \tn % Row Count 1 (+ 1) % Row 1 \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{2 - Braces \{ \}} \tn % Row Count 2 (+ 1) % Row 2 \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{3 - Tildes \textasciitilde{}} \tn % Row Count 3 (+ 1) % Row 3 \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{4 - Parameters / variables \$\{ \}} \tn % Row Count 4 (+ 1) % Row 4 \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{5 - Arithmetic \$(( ))} \tn % Row Count 5 (+ 1) % Row 5 \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{6 - Commands \$( )} \tn % Row Count 6 (+ 1) % Row 6 \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{7 - Word splitting (again)} \tn % Row Count 7 (+ 1) % Row 7 \SetRowColor{white} \mymulticolumn{1}{x{8.4cm}}{8 - Pathnames ./*} \tn % Row Count 8 (+ 1) % Row 8 \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{9 - Process substitution \textless{}( )} \tn % Row Count 9 (+ 1) \hhline{>{\arrayrulecolor{DarkBackground}}-} \SetRowColor{LightBackground} \mymulticolumn{1}{x{8.4cm}}{Only brace expansion, word splitting, pathname expansion, "\$@" and "\$\{name{[}@{]}\}" can change the number of words of the expansion; other expansions expand a single word to a single word.} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{x{1.76 cm} x{6.24 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{8.4cm}}{\bf\textcolor{white}{Command expansion}} \tn % Row 0 \SetRowColor{LightBackground} \seqsplit{\$(command)} & Replaces the command substitution with the standard output of the command \tn % Row Count 3 (+ 3) % Row 1 \SetRowColor{white} \textbackslash{}`command\textbackslash{}` & Same as above but backslash retains its literal meaning unless escaped \tn % Row Count 6 (+ 3) \hhline{>{\arrayrulecolor{DarkBackground}}--} \SetRowColor{LightBackground} \mymulticolumn{2}{x{8.4cm}}{If the substitution appears within double quotes, word splitting and pathname expansion are not performed on the results.} \tn \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{x{1.6 cm} x{6.4 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{8.4cm}}{\bf\textcolor{white}{Process Substitution}} \tn % Row 0 \SetRowColor{LightBackground} \textless{}(process) & Substitutes with the standard output fd of process \tn % Row Count 2 (+ 2) % Row 1 \SetRowColor{white} \textgreater{}(process) & Substitutes with the standard input fd of process \tn % Row Count 4 (+ 2) \hhline{>{\arrayrulecolor{DarkBackground}}--} \SetRowColor{LightBackground} \mymulticolumn{2}{x{8.4cm}}{Similar to piping but acts with files (named pipes), allowing them to work with commands that do not accept standard input unlike pipes, and allows working with multiple inputs/outputs without `... | tee`} \tn \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{x{2.16 cm} x{5.84 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{8.4cm}}{\bf\textcolor{white}{Arithmetic Expansion}} \tn % Row 0 \SetRowColor{LightBackground} \seqsplit{\$((expression))} & Evaluates expression as an arithmetic expression \tn % Row Count 2 (+ 2) \hhline{>{\arrayrulecolor{DarkBackground}}--} \SetRowColor{LightBackground} \mymulticolumn{2}{x{8.4cm}}{{\emph{Operator precedence, associativity, and values are the same as in C.}} Shell variables can be used raw without \$. Evaluation is done in fixed-width integers. Prefixes indicate bases: "0" for octal, "0x" for hex, "n\#" for base n.} \tn \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{x{2.16 cm} x{5.84 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{8.4cm}}{\bf\textcolor{white}{Pattern Matching}} \tn % Row 0 \SetRowColor{LightBackground} \textbackslash{} & Escapes next character \tn % Row Count 1 (+ 1) % Row 1 \SetRowColor{white} * & Matches any string incl null string. \tn % Row Count 3 (+ 2) % Row 2 \SetRowColor{LightBackground} ? & Matches any single char \tn % Row Count 4 (+ 1) % Row 3 \SetRowColor{white} {[}...{]} & As regex \tn % Row Count 5 (+ 1) % Row 4 \SetRowColor{LightBackground} \seqsplit{?(pattern-list)} & Matches 0 or 1 instance of one of the patterns separated by | \tn % Row Count 8 (+ 3) % Row 5 \SetRowColor{white} \seqsplit{*(pattern-list)} & Matches 0+ instances of one of the patterns separated by | \tn % Row Count 10 (+ 2) % Row 6 \SetRowColor{LightBackground} \seqsplit{+(pattern-list)} & Matches 1+ instances of one of the patterns separated by | \tn % Row Count 12 (+ 2) % Row 7 \SetRowColor{white} \seqsplit{@(pattern-list)} & Matches exactly 1 instance of one of the patterns separated by | \tn % Row Count 15 (+ 3) % Row 8 \SetRowColor{LightBackground} !(pattern-list) & Matches anything except one of the patterns separated by | \tn % Row Count 17 (+ 2) % Row 9 \SetRowColor{white} ** & When globstar is enabled, matches all files, dirs, subdirs and files in subdirs \tn % Row Count 20 (+ 3) \hhline{>{\arrayrulecolor{DarkBackground}}--} \SetRowColor{LightBackground} \mymulticolumn{2}{x{8.4cm}}{"Pattern list" patterns require the {\emph{extglob}} option to be enabled. \newline Works in case statements, == and != inside {[}{[} {]}{]}, case modification, pattern match variable expansion and filename expansion if the "pattern characters" are not quoted.} \tn \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{x{3.28 cm} x{4.72 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{8.4cm}}{\bf\textcolor{white}{I/O redirection}} \tn % Row 0 \SetRowColor{LightBackground} command {[}n{]}\textless{} file & Opens file for reading and redirects fd n (default 0, stdin) of command to file \tn % Row Count 4 (+ 4) % Row 1 \SetRowColor{white} command {[}n{]}\textgreater{} file & Opens file for writing and redirects fd n (default 1, stdout) of command to file \tn % Row Count 8 (+ 4) % Row 2 \SetRowColor{LightBackground} \&\textgreater{}file & Redirects both stdin and stderr to file. Same as `\textgreater{}word 2\textgreater{}\&1` \tn % Row Count 11 (+ 3) % Row 3 \SetRowColor{white} \&\textgreater{}\textgreater{}file & Same as above but appends \tn % Row Count 13 (+ 2) % Row 4 \SetRowColor{LightBackground} \textless{}\textless{}word\{\{nl\}\}text\{\{nl\}\}word & Substitute standard input with text (can be multiple lines) \tn % Row Count 16 (+ 3) % Row 5 \SetRowColor{white} \textless{}\textless{}-word\{\{nl\}\}text\{\{nl\}\}word & As above but strips tabs from text and final word \tn % Row Count 19 (+ 3) % Row 6 \SetRowColor{LightBackground} \textless{}\textless{}"word"\{\{nl\}\}text\{\{nl\}\}word & As \textless{}\textless{}word but do not perform parameter expansion, command substitution, and arithmetic expansion in text \tn % Row Count 24 (+ 5) % Row 7 \SetRowColor{white} \textless{}\textless{}\textless{}word & Supplies word as a single line to fd n (default stdin) \tn % Row Count 27 (+ 3) % Row 8 \SetRowColor{LightBackground} {[}n{]}\textless{}\&word & File descriptor n is made to be a copy of fd word for input \tn % Row Count 30 (+ 3) \end{tabularx} \par\addvspace{1.3em} \vfill \columnbreak \begin{tabularx}{8.4cm}{x{3.28 cm} x{4.72 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{8.4cm}}{\bf\textcolor{white}{I/O redirection (cont)}} \tn % Row 9 \SetRowColor{LightBackground} {[}n{]}\textgreater{}\&word & Same as above but for output \tn % Row Count 2 (+ 2) % Row 10 \SetRowColor{white} {[}n{]}\textless{}\&digit- & Moves fd digit to fd n (default stdin) and closes digit \tn % Row Count 5 (+ 3) % Row 11 \SetRowColor{LightBackground} {[}n{]}\textgreater{}\&digit- & Same but for output (default stdout) \tn % Row Count 7 (+ 2) % Row 12 \SetRowColor{white} {[}n{]}\textless{}\textgreater{}word & Opens word for reading and writing on fd n \tn % Row Count 9 (+ 2) \hhline{>{\arrayrulecolor{DarkBackground}}--} \SetRowColor{LightBackground} \mymulticolumn{2}{x{8.4cm}}{A fd number can be prepended to most forms in order to redirect to another fd instead of the default stdin/out/err.} \tn \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{8.4cm}{x{1.44 cm} x{6.56 cm} } \SetRowColor{DarkBackground} \mymulticolumn{2}{x{8.4cm}}{\bf\textcolor{white}{Grouping Commands}} \tn % Row 0 \SetRowColor{LightBackground} (list) & Executes the commands in a subshell \tn % Row Count 2 (+ 2) % Row 1 \SetRowColor{white} \{ list; \} & Executes the commands in the current environment \tn % Row Count 4 (+ 2) \hhline{>{\arrayrulecolor{DarkBackground}}--} \SetRowColor{LightBackground} \mymulticolumn{2}{x{8.4cm}}{The exit status of both of these constructs is the exit status of list. See pipefail option.} \tn \hhline{>{\arrayrulecolor{DarkBackground}}--} \end{tabularx} \par\addvspace{1.3em} % That's all folks \end{multicols*} \end{document}