BASH-BUILTINS(7)

๐Ÿ“ฆ version 5.2.37, in ubuntu questing

โœจ BASH-BUILTINS(7) โœจ

Miscellaneous Information Manual ๐Ÿ’– bash-builtins is the section 7 page for bash's built-in commands. Full details live in bash(1), bestie ๐Ÿซถ


๐ŸŒธ NAME ๐ŸŒธ

bash-builtins - bash built-in commands, see bash(1) ๐Ÿ’…

๐Ÿฆ‹ SYNOPSIS ๐Ÿฆ‹

okay so bash comes with a whole squad of built-in commands ๐Ÿ‘‘ they are: :, ., [, alias, bg, bind, break, builtin, case, cd, command, compgen, complete, continue, declare, dirs, disown, echo, enable, eval, exec, exit, export, fc, fg, getopts, hash, help, history, if, jobs, kill, let, local, logout, popd, printf, pushd, pwd, read, readonly, return, set, shift, shopt, source, suspend, test, times, trap, type, typeset, ulimit, umask, unalias, unset, until, wait, while โœจ

๐ŸŽ€ BASH BUILTIN COMMANDS ๐ŸŽ€

Okay, the big vibe check on options ๐Ÿ’œ Unless I say otherwise, every builtin in this section that takes options with - accepts -- to mark the end of the options ๐Ÿ™ˆ The :, true, false, and test/[ builtins don't take options at all, so they don't treat -- specially. The exit, logout, return, break, continue, let, and shift builtins accept and process arguments that start with - without needing -- ๐Ÿ”ฅ Any other builtin that takes arguments but doesn't take options will treat a - argument as a bad option, so you need -- to stop that from happening ๐Ÿ’€

: [arguments]

Literally does nothing ๐Ÿ˜ญ It expands the arguments and does any redirections you asked for, and that's it. The return status is zero, so it always passes โœจ

. filename [arguments]

source filename [arguments]

This one reads and runs commands from filename inside your current shell environment ๐Ÿงš It returns the exit status of the last command run from filename. If filename doesn't have a slash, bash looks through the directories in PATH to find the one containing it, and the file doesn't have to be executable ๐Ÿ’œ When bash isn't in posix mode and nothing shows up in PATH, it checks the current directory too. If the sourcepath option of the shopt builtin is turned off, PATH doesn't get searched at all ๐Ÿ™ˆ If you pass any arguments, they become the positional parameters while filename runs. If you don't, the positional parameters stay the same โœจ

Trap stuff is a whole thing ๐Ÿ”ฅ If the -T option is enabled, . inherits any trap on DEBUG. If it isn't, any DEBUG trap string gets saved and restored around the call to ., and . unsets the DEBUG trap while it's running. If -T isn't set and the sourced file changes the DEBUG trap, that new value sticks around once . finishes ๐Ÿ‘‘

The return status is the status of the last command that exited inside the script (0 if nothing ran). It returns false if filename can't be found or can't be read ๐Ÿ’€

alias [-p] [name[=value] ...]

No arguments, or just the -p option? Then alias prints every alias as alias name=value on standard output ๐Ÿ’– When you do give arguments, an alias gets defined for each name that has a value. A trailing space in value means the next word also gets checked for alias substitution when the alias is expanded ๐Ÿฆ‹ For any name in the list with no value, alias prints that name and its alias value. alias returns true unless you give a name that has no alias defined ๐Ÿซถ

bg [jobspec ...]

Resumes each suspended job jobspec in the background, like it was started with & ๐ŸŒˆ If you skip jobspec, bash uses its idea of the current job. bg jobspec returns 0 unless it's run while job control is disabled ๐Ÿ’… With job control on, it returns non-zero if a specified jobspec wasn't found or was started without job control ๐Ÿ˜ญ

bind [-m keymap] [-lpsvPSVX]

bind [-m keymap] [-q function] [-u function] [-r keyseq]

bind [-m keymap] -f filename

bind [-m keymap] -x keyseq:shell-command

bind [-m keymap] keyseq:function-name

bind [-m keymap] keyseq:readline-command

bind readline-command-line

Okay this one is giving readline energy โœจ bind can show your current readline key and function bindings, bind a key sequence to a readline function or macro, or set a readline variable ๐ŸŽ€ Every non-option argument is a command written the way it would be in a readline init file like .inputrc, but each binding or command has to be its own separate argument. For example: '"\C-x\C-r": re-read-init-file' ๐Ÿงš Here's what the options do:

  • -m keymap โ€” uses keymap for the bindings that come after it ๐Ÿ—๏ธ The keymap names you can use are emacs, emacs-standard, emacs-meta, emacs-ctlx, vi, vi-move, vi-command, and vi-insert. vi is the same as vi-command (vi-move is also a synonym), and emacs is the same as emacs-standard ๐Ÿ’œ
  • -l โ€” lists the names of all readline functions ๐Ÿ“œ
  • -p โ€” shows readline function names and bindings in a format you can re-read ๐Ÿซถ
  • -P โ€” lists the current readline function names and bindings ๐Ÿ’…
  • -s โ€” shows readline key sequences bound to macros, plus the strings they output, in a re-readable format ๐ŸŒธ
  • -S โ€” shows readline key sequences bound to macros and the strings they output ๐Ÿฆ‹
  • -v โ€” shows readline variable names and values in a re-readable format ๐Ÿ“
  • -V โ€” lists the current readline variable names and values โœจ
  • -f filename โ€” reads key bindings from filename ๐Ÿ“‚
  • -q function โ€” asks which keys trigger the named function ๐Ÿ”
  • -u function โ€” unbinds every key bound to the named function ๐Ÿšซ
  • -r keyseq โ€” removes any current binding for keyseq ๐Ÿ—‘๏ธ
  • -x keyseq:shell-command โ€” makes shell-command run whenever keyseq gets typed ๐Ÿ”ฅ When it runs, bash sets the READLINE_LINE variable to the contents of the readline line buffer, and READLINE_POINT and READLINE_MARK to the current insertion point and the saved insertion point (the mark), in that order ๐Ÿงš If the user gave a numeric argument, bash assigns it to READLINE_ARGUMENT. If there wasn't one, that variable doesn't get set at all ๐Ÿ™ˆ If the command changes READLINE_LINE, READLINE_POINT, or READLINE_MARK, those new values show up in the editing state ๐ŸŒˆ
  • -X โ€” lists every key sequence bound to shell commands, plus the commands themselves, in a format you can feed back in as input ๐ŸŽ€

The return value is 0 unless you pass an unrecognized option or something errors out ๐Ÿ’€

break [n]

Exits from inside a for, while, until, or select loop ๐Ÿ’– If you give n, it breaks out of n levels. n must be โ‰ฅ 1 ๐Ÿซถ If n is bigger than the number of loops you're in, all the enclosing loops get exited ๐Ÿ‘‘ The return value is 0 unless n is not greater than or equal to 1 โœจ

builtin shell-builtin [arguments]

Runs the shell builtin you named, passes it the arguments, and returns its exit status ๐Ÿฆ‹ This is super handy when you write a function with the same name as a builtin and still want the builtin's behavior inside that function ๐Ÿงš The cd builtin gets redefined like this all the time ๐Ÿ’… The return status is false if shell-builtin isn't a shell builtin command ๐Ÿ’€

caller [expr]

Returns the context of any active subroutine call, which means a shell function or a script run with . or source ๐Ÿ”ฅ With no expr, caller shows the line number and source filename of the current subroutine call. If you give it a non-negative integer as expr, caller shows the line number, subroutine name, and source file for that spot in the current execution call stack ๐ŸŒˆ You could use this info to print a stack trace, for example ๐Ÿซถ Frame 0 is the current frame ๐Ÿ’œ The return value is 0 unless the shell isn't running a subroutine call, or expr doesn't match a valid spot in the call stack ๐Ÿ˜ญ

cd [-L|[-P [-e]] [-@]] [dir]

Changes the current directory to dir ๐Ÿ’– If you don't supply dir, the value of the HOME shell variable is used by default ๐Ÿก The CDPATH variable is the search path for the directory that holds dir: each directory name in CDPATH gets searched for dir. Multiple directories in CDPATH are separated by a colon (:) ๐Ÿงš A null directory name in CDPATH means the current directory, which is . ๐Ÿฆ‹ If dir begins with a slash (/), CDPATH doesn't get used ๐Ÿ™…

Now the -P and -L options, which are kind of a big deal ๐Ÿ’… -P makes cd use the physical directory structure by resolving symbolic links while it walks through dir, and it does that before it handles any .. in dir (see also the -P option of the set builtin). -L forces symbolic links to be followed by resolving the link after it handles any .. in dir ๐Ÿ”ฅ If .. shows up in dir, it gets handled by removing the component right before it, going back to a slash or the start of dir ๐ŸŒˆ If you pass -e together with -P, and the current working directory can't be figured out after a successful directory change, cd returns an unsuccessful status ๐Ÿ˜ญ

On systems that support it, the -@ option shows the extended attributes of a file as a directory ๐Ÿซถ An argument of - gets converted to $OLDPWD before the directory change is tried ๐Ÿ“ If a non-empty directory name from CDPATH gets used, or - is the first argument, and the change works, the absolute pathname of the new working directory is written to standard output โœจ

When the change succeeds, cd sets the PWD environment variable to the new directory name, and sets OLDPWD to whatever the working directory was before the change ๐Ÿ’– The return value is true if the directory was changed successfully, and false otherwise ๐Ÿ’œ

โœจ command โœจ

command [-pVv] command [arg ...]

okay so command lets you run a command with its args while skipping the normal shell function lookup ๐Ÿ’… Only builtin commands or commands found in the PATH will actually run. ๐Ÿซถ

  • -p โ€” the search for command uses a default value for PATH that is guaranteed to find all of the standard utilities ๐ŸŒธ
  • -V โ€” gives you a more verbose description of command ๐Ÿ“–
  • -v โ€” shows a single word naming the command or filename used to invoke command ๐Ÿฆ‹

If you use -V or -v, the exit status is 0 if the command was found and 1 if it wasn't. โœจ If you use neither, and there was an error or the command can't be found, the exit status is 127. Otherwise the exit status of command is just the exit status of command. ๐Ÿ’–


โœจ compgen โœจ

compgen [option] [word]

bestie, compgen generates possible completion matches for word and writes them to standard output ๐Ÿงš The options can be any option the complete builtin accepts, except -p and -r. ๐ŸŽ€

It makes the matches the exact same way the programmable completion code would if it generated them from a completion specification with the same flags. ๐ŸŒˆ If you give it a word, only the completions that match that word get shown. ๐Ÿ“

When you use -F or -C, the shell variables set by the programmable completion facilities won't have useful values. (They might exist, but they're not gonna be helpful, so don't count on them ๐Ÿ™ˆ)

The return value is true unless you pass an invalid option or no matches were generated. ๐Ÿ’€


โœจ complete โœจ

complete [-abcdefgjksuv] [-o comp-option] [-DEI] [-A action] [-G globpat] [-W wordlist]
         [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix]
         name [name ...]
complete -pr [-DEI] [name ...]

so complete is how you decide how the arguments to each name get completed ๐Ÿ‘‘ If you pass -p, or no options at all, your existing completion specs get printed in a way that you can copy-paste right back in as input ๐Ÿ’œ That's lowkey the best part. ๐Ÿซถ

The -r option removes a completion spec for each name. If you don't give any names, it removes all of them. ๐Ÿ˜ญ

Now the special flags ๐Ÿ”ฅ

  • -D โ€” the other options and actions apply to the "default" command completion, meaning completion tried on a command that doesn't have any completion defined yet ๐ŸŒธ
  • -E โ€” the other options and actions apply to "empty" command completion, meaning completion tried on a blank line โœจ
  • -I โ€” the other options and actions apply to the initial non-assignment word on the line, or the word after a command delimiter like ; or |. This is usually command name completion ๐Ÿฆ‹

If you pass more than one of these, -D beats -E, and both of them beat -I. ๐Ÿ‘‘ And if you pass any of -D, -E, or -I, any other name arguments get ignored, because those completions only apply to the case you picked. ๐Ÿ™ˆ

The process of applying these completion specs when word completion is attempted is described in bash(1). ๐Ÿ“–

Okay, here are the other options and what they mean. Heads up: the arguments to -G, -W, and -X (and -P and -S if needed) should be quoted so they don't get expanded before the complete builtin is invoked. ๐Ÿ’…

  • -a, -b, -c, -d, -e, -f, -g, -j, -k, -s, -u, -v โ€” these are shortcuts for the -A actions listed below. Check the -A section for which letter goes with which action ๐Ÿงš
  • -o comp-option โ€” the comp-option controls a bunch of stuff about the compspec's behavior, beyond just generating completions ๐ŸŒˆ It can be one of these:
    • bashdefault โ€” does the rest of the default bash completions if the compspec doesn't make any matches ๐Ÿ’–
    • default โ€” uses readline's default filename completion if the compspec doesn't make any matches ๐ŸŽ€
    • dirnames โ€” does directory name completion if the compspec doesn't make any matches ๐Ÿ“
    • filenames โ€” tells readline the compspec makes filenames, so readline can do filename stuff like adding a slash to directories, quoting special characters, or skipping the trailing space. This is meant for shell functions ๐Ÿฆ‹
    • noquote โ€” tells readline not to quote the completed words if they're filenames. (Quoting filenames is the default, fyi ๐Ÿ’…)
    • nosort โ€” tells readline not to sort the possible completions alphabetically ๐Ÿ“
    • nospace โ€” tells readline not to add a space (which is the default) to words completed at the end of the line ๐ŸŒธ
    • plusdirs โ€” after the compspec's matches are generated, directory name completion gets tried too, and any matches get added to the results from the other actions โœจ
  • -A action โ€” the action can be one of these, to generate a list of possible completions ๐Ÿ‘‘
    • alias โ€” alias names. Can also be written as -a ๐Ÿงš
    • arrayvar โ€” array variable names ๐ŸŒˆ
    • binding โ€” readline key binding names ๐ŸŽ€
    • builtin โ€” names of shell builtin commands. Can also be written as -b ๐Ÿ’–
    • command โ€” command names. Can also be written as -c ๐Ÿฆ‹
    • directory โ€” directory names. Can also be written as -d ๐Ÿ“
    • disabled โ€” names of disabled shell builtins ๐Ÿ™ˆ
    • enabled โ€” names of enabled shell builtins โœจ
    • export โ€” names of exported shell variables. Can also be written as -e ๐Ÿ“
    • file โ€” file names. Can also be written as -f ๐Ÿ“„
    • function โ€” names of shell functions ๐Ÿ’œ
    • group โ€” group names. Can also be written as -g ๐Ÿซถ
    • helptopic โ€” help topics that the help builtin accepts ๐Ÿ“–
    • hostname โ€” hostnames, taken from the file that the HOSTFILE shell variable points to ๐ŸŒธ
    • job โ€” job names, if job control is active. Can also be written as -j ๐Ÿ”ฅ
    • keyword โ€” shell reserved words. Can also be written as -k ๐Ÿ’…
    • running โ€” names of running jobs, if job control is active ๐Ÿƒโ€โ™€๏ธ
    • service โ€” service names. Can also be written as -s โญ
    • setopt โ€” valid arguments for the -o option to the set builtin ๐ŸŽ€
    • shopt โ€” shell option names that the shopt builtin accepts ๐ŸŒˆ
    • signal โ€” signal names ๐Ÿ’ฅ
    • stopped โ€” names of stopped jobs, if job control is active ๐Ÿ›‘
    • user โ€” user names. Can also be written as -u ๐Ÿงš
    • variable โ€” names of all shell variables. Can also be written as -v ๐Ÿ’œ
  • -C command โ€” the command runs in a subshell environment, and its output becomes the possible completions ๐Ÿฆ‹ The arguments get passed the same way as with -F. ๐ŸŒธ
  • -F function โ€” the shell function function runs in the current shell environment ๐Ÿ‘‘ When it runs, $1 is the name of the command whose arguments are being completed, $2 is the word being completed, and $3 is the word right before the word being completed on the current command line. ๐Ÿงš When it finishes, the possible completions come from the COMPREPLY array variable. ๐Ÿ’–
  • -G globpat โ€” the pathname expansion pattern globpat gets expanded to make the possible completions ๐ŸŒˆ
  • -P prefix โ€” prefix gets added to the beginning of each possible completion, after all the other options have been applied ๐ŸŽ€
  • -S suffix โ€” suffix gets appended to each possible completion, after all the other options have been applied ๐Ÿ“
  • -W wordlist โ€” the wordlist gets split using the characters in the IFS special variable as delimiters, and then each word gets expanded. Shell quoting works inside wordlist, so the words can have shell metacharacters or characters from the value of IFS in them ๐Ÿ’… The possible completions are the members of that list that match the word being completed. โœจ
  • -X filterpat โ€” filterpat is a pattern, the same kind used for pathname expansion ๐Ÿซถ It gets applied to the list of possible completions made by the options and arguments before it, and any completion matching filterpat gets removed. ๐Ÿ™ˆ If filterpat starts with a !, that negates it, so any completion that does not match gets removed instead. ๐Ÿ”ฅ

The return value is true unless you pass an invalid option, pass an option other than -p or -r without a name argument, try to remove a completion spec for a name that doesn't have one, or an error happens while adding a completion spec. ๐Ÿ’€

โœจ compopt โœจ

compopt [-o option] [-DEI] [+o option] [name]

okay so compopt lets you tweak completion options for each name you give it ๐Ÿ’… or, if you don't name anything, for whatever completion is running right now ๐Ÿซถ. No options at all? It just shows you the completion options for each name (or the current completion) ๐Ÿ‘€. The valid option values are the same ones the complete builtin takes, so go check that one ๐ŸŒธ.

  • -D โ€” applies your other options to the "default" command completion, aka completion on a command that doesn't have any completion set up yet ๐Ÿงš
  • -E โ€” applies them to "empty" command completion, which is when you hit tab on a blank line ๐Ÿซ 
  • -I โ€” applies them to the first non-assignment word on the line, or anything right after a command delimiter like ; or |. This is usually command name completion ๐Ÿ’œ

The return value is true unless you pass an invalid option, try to change the options for a name that has no completion spec (rude ๐Ÿ’€), or an output error happens ๐Ÿ˜ญ.


โœจ continue โœจ

continue [n]

continue skips ahead to the next loop iteration of the enclosing for, while, until, or select loop ๐Ÿฆ‹. Give it an n and it jumps to the nth enclosing loop instead ๐ŸŒˆ. n has to be โ‰ฅ 1, no cap ๐Ÿ™…โ€โ™€๏ธ. If n is bigger than how many loops you're in, it just goes to the last enclosing loop (the "top-level" one) ๐Ÿ‘‘. The return value is 0 unless n is not greater than or equal to 1 ๐Ÿ”ฅ.


โœจ declare / typeset โœจ

declare [-aAfFgiIlnrtux] [-p] [name[=value] ...]
typeset [-aAfFgiIlnrtux] [-p] [name[=value] ...]

declare (and its twin typeset) lets you make variables and give them attributes ๐Ÿ’–. No names? It shows you the values of variables โœจ. The -p flag shows the attributes and values of each name ๐ŸŽ€. If you use -p with names, any extra options except -f and -F get ignored, so don't stress ๐Ÿ™ˆ. -p without names shows everything with the attributes you asked for, and if you add no other options, you get every shell variable ๐Ÿงš.

  • -f โ€” only shows shell functions ๐ŸŒธ
  • -F โ€” hides the function definitions, so you only see the name and attributes ๐Ÿ™ˆ. Turning on the extdebug shell option with shopt also shows the source file name and line number where each name was defined ๐Ÿ“
  • -F also implies -f ๐Ÿ’…
  • -g โ€” forces variables to be created or changed at the global scope, even inside a shell function ๐ŸŒ. It does nothing anywhere else ๐Ÿคทโ€โ™€๏ธ
  • -I โ€” makes local variables inherit the attributes (except nameref) and value of any existing variable with the same name from a surrounding scope โœจ. If there's nothing to inherit, the local variable starts out unset ๐Ÿซฅ

These options restrict output to variables with a certain attribute, or give variables attributes:

  • -a โ€” each name is an indexed array variable (see Arrays in bash(1)) ๐ŸŒˆ
  • -A โ€” each name is an associative array variable (see Arrays in bash(1)) ๐Ÿ’œ
  • -f โ€” use function names only ๐Ÿฆ‹
  • -i โ€” the variable is treated as an integer, so arithmetic evaluation (see ARITHMETIC EVALUATION in bash(1)) happens whenever you assign it a value ๐Ÿ”ข
  • -l โ€” any upper-case characters get converted to lower-case when you assign a value, and the upper-case attribute gets turned off ๐Ÿ“
  • -n โ€” gives each name the nameref attribute, so it's a name reference to whatever variable its value names ๐Ÿชž. All references, assignments, and attribute changes go to that other variable, except ones that use or change -n itself. nameref can't be applied to array variables ๐Ÿ™…โ€โ™€๏ธ
  • -r โ€” makes names readonly ๐Ÿ”’. Later assignments or unset can't touch them
  • -t โ€” gives each name the trace attribute ๐Ÿ”. Traced functions inherit the DEBUG and RETURN traps from the calling shell. Trace doesn't mean anything special for variables ๐Ÿคทโ€โ™€๏ธ
  • -u โ€” any lower-case characters get converted to upper-case when you assign a value, and the lower-case attribute gets turned off ๐Ÿ” 
  • -x โ€” marks names for export to later commands through the environment ๐ŸŒฟ

Use + instead of - to turn an attribute off, with two exceptions: +a and +A can't destroy array variables, and +r won't remove the readonly attribute ๐Ÿ”. When you use these inside a function, declare and typeset make each name local, just like the local command, unless you pass -g โœจ. If a name is followed by =value, the variable gets set to that value ๐Ÿ’–. When you use -a or -A with compound assignment syntax to create array variables, extra attributes only kick in on later assignments ๐Ÿ™ƒ.

The return value is 0 unless one of these happens: you hit an invalid option, you try to define a function with -f foo=bar, you try to assign to a readonly variable, you try to assign a value to an array without the compound assignment syntax (see Arrays in bash(1)), a name isn't a valid shell variable name, you try to turn off readonly on a readonly variable, you try to turn off array status for an array variable, or you try to display a non-existent function with -f ๐Ÿ˜ญ.

โš ๏ธ these all error out, so don't say I didn't warn you bestie ๐Ÿ’€

โœจ dirs โœจ

dirs [-clpv] [+n] [-n]

With no options, dirs shows you the directories the shell is currently remembering ๐Ÿ“‚, all on one line separated by spaces ๐ŸŒธ. Directories get added with pushd, and popd removes them ๐Ÿงš. The current directory is always the first one in the stack ๐Ÿ‘‘.

  • -c โ€” clears the directory stack by deleting every entry ๐Ÿงน
  • -l โ€” gives you a listing with full pathnames. The default format uses a tilde for the home directory ๐Ÿ 
  • -p โ€” prints the directory stack with one entry per line ๐Ÿ“
  • -v โ€” prints one entry per line, each one prefixed with its index in the stack ๐Ÿ”ข
  • +n โ€” shows the *n*th entry counting from the left of the list (starting at zero) โฌ…๏ธ
  • -n โ€” shows the *n*th entry counting from the right of the list (starting at zero) โžก๏ธ

The return value is 0 unless you pass an invalid option or n goes past the end of the directory stack ๐Ÿ™ˆ.


โœจ disown โœจ

disown [-ar] [-h] [jobspec ... | pid ... ]

Without options, disown removes each jobspec from the table of active jobs ๐Ÿ‘‹. If you don't give a jobspec and you skip both -a and -r, it goes after the current job ๐ŸŽฏ. With -h, the job stays in the table, but it gets marked so SIGHUP doesn't get sent to it if the shell receives a SIGHUP ๐Ÿ›ก๏ธ. If you don't supply a jobspec, -a means remove or mark all jobs, and -r by itself (no jobspec) limits things to running jobs ๐Ÿƒโ€โ™€๏ธ. The return value is 0 unless a jobspec doesn't point to a valid job ๐Ÿ˜ค.


โœจ echo โœจ

echo [-neE] [arg ...]

echo outputs the args, separated by spaces, then a newline ๐Ÿ“ฃ. Its return status is 0 unless a write error happens ๐Ÿ’…. -n suppresses that trailing newline ๐Ÿ™Š. -e turns on interpretation of the backslash-escaped characters below ๐ŸŽ€. -E turns that interpretation off, even on systems where it's on by default ๐Ÿšซ. The xpg_echo shell option can decide dynamically whether echo expands those escape characters by default โš™๏ธ. Heads up: echo doesn't treat -- as the end of options ๐Ÿ™ƒ.

Here are the escape sequences echo understands:

  • \a โ€” alert (bell) ๐Ÿ””
  • \b โ€” backspace โฌ…๏ธ
  • \c โ€” suppress further output ๐Ÿค
  • \e and \E โ€” an escape character ๐ŸŒ€
  • \f โ€” form feed ๐Ÿ“„
  • \n โ€” new line โŽ
  • \r โ€” carriage return โ†ฉ๏ธ
  • \t โ€” horizontal tab โžก๏ธ
  • \v โ€” vertical tab โฌ‡๏ธ
  • \\ โ€” backslash ๐Ÿฆฉ
  • \0nnn โ€” the eight-bit character whose value is the octal value nnn (zero to three octal digits) ๐Ÿ”ข
  • \xHH โ€” the eight-bit character whose value is the hexadecimal value HH (one or two hex digits) ๐Ÿงฎ
  • \uHHHH โ€” the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value HHHH (one to four hex digits) ๐ŸŒ
  • \UHHHHHHHH โ€” the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value HHHHHHHH (one to eight hex digits) ๐ŸŒˆโœจ

๐ŸŽ€ enable

enable [-a] [-dnps] [-f filename] [name ...]

okay so disabling a builtin lets a disk command with the same name run without a full pathname, even tho the shell normally checks builtins first ๐Ÿ‘€ โœจ If you use -n, each name gets disabled. Otherwise, the names get enabled. For example, to use the test binary from your PATH instead of the shell's builtin version, run enable -n test ๐Ÿ’…

  • -f โ€” loads a new builtin from a shared object filename ๐Ÿฆ‹ (only on systems that support dynamic loading). Bash searches the directories in the BASH_LOADABLES_PATH variable, which is a colon-separated list, to find filename. The default is system-dependent ๐ŸŒˆ
  • -d โ€” deletes a builtin you loaded earlier with -f ๐Ÿ—‘๏ธ
  • -p โ€” prints a list of shell builtins. If you give no name arguments, you get the list anyway ๐Ÿ“œ
  • -n โ€” when printing, only the disabled builtins show up ๐Ÿ™ˆ
  • -a โ€” prints every builtin and shows whether each one is enabled or not โœจ
  • -s โ€” limits the output to the POSIX special builtins ๐Ÿ”ฅ

With no other option arguments, the list is just all the enabled shell builtins. If you give no options and a name isn't a shell builtin, enable will try to load that name from a shared object called name, as if you'd written enable -f name name ๐Ÿงš

The return value is 0 unless a name isn't a shell builtin, or there's an error loading a new builtin from a shared object. no cap, that's the whole thing ๐Ÿ’œ


๐Ÿ’ซ eval

eval [arg ...]

the args get read and smooshed together into one single command ๐Ÿ’– Then the shell reads and runs that command, and its exit status becomes the value of eval โœจ If there are no args, or only null arguments, eval returns 0 ๐Ÿซถ


๐Ÿฆข exec

exec [-cl] [-a name] [command [arguments]]

if you give a command, it replaces the shell ๐Ÿ˜ญ No new process gets made! The arguments become the arguments for that command ๐ŸŒธ

  • -l โ€” puts a dash at the beginning of the zeroth argument passed to the command. This is what login(1) does ๐Ÿ”‘
  • -c โ€” runs the command with an empty environment ๐Ÿซง
  • -a name โ€” the shell passes name as the zeroth argument to the command you run ๐ŸŽ€

If the command can't run for some reason, a non-interactive shell exits, unless the execfail shell option is enabled. In that case, it returns failure instead ๐Ÿ’€ An interactive shell returns failure if the file can't be executed. A subshell exits unconditionally if exec fails ๐Ÿ™ˆ

If you don't give a command, any redirections take effect in the current shell, and the return status is 0 โœจ If there's a redirection error, the return status is 1 โŒ


๐Ÿšช exit

exit [n]

this makes the shell exit with a status of n ๐Ÿ‘‹ If you leave n out, the exit status is whatever the last command executed gave back ๐Ÿ’… A trap on EXIT runs before the shell actually terminates, so it gets the last word ๐Ÿ‘‘


๐ŸŒท export

export [-fn] [name[=word]] ...
export -p

the names you supply get marked for automatic export to the environment of commands run afterwards ๐ŸŒˆ With -f, the names refer to functions instead of variables ๐Ÿงš If you give no names, or you use -p, you get a list of the names of all the exported variables ๐Ÿ“œ

  • -n โ€” removes the export property from each name ๐Ÿšซ
  • name=word โ€” if a variable name is followed by =word, its value gets set to word ๐Ÿ’–

export returns an exit status of 0 unless you hit an invalid option, one of the names isn't a valid shell variable name, or you use -f with a name that isn't a function ๐Ÿ˜ฌ


๐Ÿงพ fc

fc [-e ename] [-lnr] [first] [last]
fc -s [pat=rep] [cmd]

the first form picks a range of commands from first to last out of the history list, then either displays them, or edits and re-runs them ๐Ÿ•ฐ๏ธ First and last can be a string (to find the last command starting with that string) or a number (an index into the history list, where a negative number is an offset from the current command number) ๐Ÿ”ข

Here's the tea on the numbers: when you're listing, a first or last of 0 is the same as -1, and -0 is the current command (usually the fc command itself) ๐Ÿ’… Otherwise, 0 is the same as -1, and -0 is invalid ๐Ÿ™…โ€โ™€๏ธ

If last isn't specified, it's set to the current command when listing (so fc -l -10 prints the last 10 commands), and set to first otherwise ๐Ÿ’ซ If first isn't specified, it's set to the previous command for editing, and -16 for listing ๐Ÿฆ‹

  • -n โ€” suppresses the command numbers when listing ๐Ÿ™ˆ
  • -r โ€” reverses the order of the commands ๐Ÿ”
  • -l โ€” lists the commands on standard output ๐Ÿ“‹

If you don't use -l, the editor named by ename gets invoked on a file full of those commands. If ename isn't given, the FCEDIT variable is used, and if FCEDIT isn't set, the EDITOR variable is used. If neither is set, vi is used ๐Ÿ–Š๏ธ When you're done editing, the edited commands are echoed and executed โœจ

In the second form, cmd gets re-run after each instance of pat is replaced by rep. Cmd is interpreted the same way as first above ๐Ÿช„ A useful alias for this is r="fc -s", so typing r cc runs the last command starting with cc, and typing r on its own re-runs the last command ๐Ÿ”ฅ

If you use the first form, the return value is 0 unless you hit an invalid option, or first or last specify history lines that are out of range. If you use -e, the return value is the value of the last command executed, or failure if an error happens with the temporary file of commands ๐Ÿ˜ญ If you use the second form, the return status is that of the re-run command, unless cmd doesn't specify a valid history line, in which case fc returns failure ๐Ÿ’€


๐Ÿƒโ€โ™€๏ธ fg

fg [jobspec]

resumes jobspec in the foreground and makes it the current job ๐Ÿ”ฅ If jobspec isn't there, the shell's idea of the current job gets used ๐Ÿ’– The return value is that of the command you put in the foreground. It's failure if you run this when job control is disabled, or, when job control is enabled, if jobspec isn't a valid job or it's a job that was started without job control ๐Ÿ™…โ€โ™€๏ธ


๐Ÿ” getopts

getopts optstring name [arg ...]

getopts is what shell procedures use to parse positional parameters ๐Ÿง optstring holds the option characters it should recognize. If a character is followed by a colon, that option is expected to have an argument, which should be separated from it by white space ๐ŸŽ€ The colon and question mark characters can't be used as option characters ๐Ÿšซ

Every time it runs, getopts puts the next option into the shell variable name (initializing name if it doesn't exist yet), and puts the index of the next argument to process into the variable OPTIND ๐Ÿ“ OPTIND is set to 1 each time the shell or a shell script is invoked. When an option needs an argument, getopts puts that argument into the variable OPTARG โœจ The shell doesn't reset OPTIND for you! If you want to use a new set of parameters between multiple calls to getopts in the same shell invocation, you have to reset it manually ๐Ÿ˜ญ

When getopts hits the end of the options, it exits with a return value greater than zero. OPTIND is set to the index of the first non-option argument, and name is set to ? ๐Ÿ

getopts normally parses the positional parameters, but if you supply more arguments as arg values, it parses those instead ๐ŸŒˆ

getopts can report errors in two ways ๐Ÿ‘€ If the first character of optstring is a colon, you get silent error reporting. In normal operation, diagnostic messages get printed when invalid options or missing option arguments show up ๐Ÿ“ฃ If the variable OPTERR is set to 0, no error messages get displayed, even if the first character of optstring isn't a colon ๐Ÿคซ

  • Invalid option โ€” getopts puts ? into name and, if it's not silent, prints an error message and unsets OPTARG. If it is silent, the option character found goes into OPTARG and no diagnostic message is printed ๐Ÿ™ˆ
  • Missing required argument โ€” if it's not silent, a question mark (?) goes into name, OPTARG gets unset, and a diagnostic message is printed. If it is silent, a colon (:) goes into name and OPTARG is set to the option character found ๐Ÿซฃ

getopts returns true if an option, specified or unspecified, is found. It returns false if the end of options is reached or an error happens ๐Ÿ’œ


๐Ÿง  hash

hash [-lr] [-p filename] [-dt] [name]

every time you invoke hash, the full pathname of the command name gets figured out by searching the directories in $PATH, and remembered ๐Ÿง  Any previously remembered pathname gets tossed out ๐Ÿ—‘๏ธ If you use -p, there's no path search at all, and filename is used as the full filename of the command ๐Ÿ“Œ

  • -r โ€” makes the shell forget all remembered locations ๐Ÿซ 
  • -d โ€” makes the shell forget the remembered location of each name ๐Ÿ‘‹
  • -t โ€” prints the full pathname each name corresponds to. If you give multiple name arguments with -t, the name gets printed before its hashed full pathname ๐Ÿช„
  • -l โ€” displays the output in a format that can be reused as input ๐Ÿ”

If you give no arguments, or only -l, you get info about the remembered commands printed out ๐Ÿ“œ

The return status is true unless a name isn't found, or you supply an invalid option ๐Ÿ’…

๐Ÿ’– help ๐Ÿ’–

okay so help is literally the bestie who explains everything ๐Ÿงšโœจ

help [-dms] [pattern]

Ask it about builtin commands and it spills the tea. Give it a pattern and you get detailed help on every command that matches. Skip the pattern and you get help for all the builtins and shell control structures ๐Ÿ“š

  • -d โ€” gives you a short description of each pattern ๐Ÿ’…
  • -m โ€” shows the description of each pattern in a manpage-like format ๐Ÿ“–
  • -s โ€” gives you only a short usage synopsis for each pattern ๐Ÿฆ‹

The return status is 0 unless no command matches pattern. no cap, that's the only way it fails ๐Ÿ’€

๐ŸŒธ history ๐ŸŒธ

the history list is giving main character energy ๐Ÿ‘‘ so many ways to use it

history [n]
history -c
history -d offset
history -d start-end
history -anrw [filename]
history -p arg [arg ...]
history -s arg [arg ...]

With no options, history shows the command history list with line numbers ๐Ÿ“œ Any line marked with a * has been modified, so keep an eye out ๐Ÿ‘€ Give it a number n and it only lists the last n lines.

Now the time stamps ๐Ÿ•ฐ๏ธ If the shell variable HISTTIMEFORMAT is set and not null, it's used as a format string for strftime(3) to show when each entry happened. There's no blank space between the formatted time stamp and the history line, so it's all squished together, which is kinda iconic โœจ If you pass a filename, that becomes the name of the history file. If not, the value of HISTFILE gets used ๐ŸŽ€

The options, if you add them, do this:

  • -c โ€” clears the history list by deleting all the entries ๐Ÿงน
  • -d offset โ€” deletes the history entry at position offset. If offset is negative, it counts relative to one greater than the last history position. So negative indices count back from the end of the history, and an index of -1 refers to the current history -d command ๐Ÿ™ˆ
  • -d start-end โ€” deletes the range of history entries between positions start and end, inclusive. Positive and negative values for start and end work the way I just described ๐Ÿ”ฅ
  • -a โ€” appends the "new" history lines to the history file. These are the ones entered since the start of the current bash session that haven't been appended yet ๐Ÿ“
  • -n โ€” reads the history lines not already read from the history file into the current history list. These are the lines appended to the history file since the start of the current bash session ๐Ÿ’œ
  • -r โ€” reads the contents of the history file and appends them to the current history list ๐ŸŒˆ
  • -w โ€” writes the current history list to the history file, overwriting whatever was in there ๐Ÿ’€
  • -p โ€” does history substitution on the following args and displays the result on the standard output. It does not store the results in the history list. Each arg has to be quoted to turn off normal history expansion, so don't skip that part ๐Ÿซถ
  • -s โ€” stores the args in the history list as a single entry. The last command in the history list gets removed before the args are added ๐Ÿ“

If HISTTIMEFORMAT is set, the time stamp info for each entry gets written to the history file, marked with the history comment character. When the history file is read, any line that starts with the history comment character right before a digit is treated as a time stamp for the entry that comes after it. so smart, right? ๐Ÿง 

The return value is 0 unless one of these happens: an invalid option shows up, an error happens while reading or writing the history file, an invalid offset or range is passed to -d, or the history expansion passed to -p fails. Anything else and you're good ๐Ÿ’…

๐Ÿฆ‹ jobs ๐Ÿฆ‹

jobs is the one that keeps track of everything you've got running ๐Ÿƒโ€โ™€๏ธ

jobs [-lnprs] [ jobspec ... ]
jobs -x command [ args ... ]

The first form lists the active jobs. Here's what the options do:

  • -l โ€” lists process IDs in addition to the normal info ๐Ÿ”ข
  • -n โ€” displays info only about jobs that have changed status since you were last notified about their status ๐Ÿ””
  • -p โ€” lists only the process ID of the job's process group leader ๐ŸŽฏ
  • -r โ€” displays only running jobs ๐Ÿƒ
  • -s โ€” displays only stopped jobs ๐Ÿ›‘

If you give it a jobspec, the output is limited to info about that one job ๐Ÿฆข The return status is 0 unless an invalid option shows up or an invalid jobspec is supplied.

If you pass the -x option, jobs swaps out any jobspec it finds in command or args for the matching process group ID. Then it runs command with args and returns its exit status. it's giving sneaky magic ๐Ÿช„

๐Ÿ”ฅ kill ๐Ÿ”ฅ

kill is not as scary as it sounds, I promise ๐Ÿ™ˆ it's just the signal sender

kill [-s sigspec | -n signum | -sigspec] [pid | jobspec] ...
kill -l|-L [sigspec | exit_status]

kill sends the signal named by sigspec or signum to the processes named by pid or jobspec. sigspec is either a case-insensitive signal name like SIGKILL (with or without the SIG prefix) or a signal number. signum is a signal number ๐Ÿ”ข If sigspec isn't there, SIGTERM gets assumed ๐Ÿ’€

An argument of -l lists the signal names. If you supply any arguments when -l is given, the names of the signals matching those arguments get listed, and the return status is 0 โœจ The exit_status argument to -l is a number that's either a signal number or the exit status of a process that got terminated by a signal. The -L option does the exact same thing as -l ๐Ÿซถ

kill returns true if at least one signal was sent successfully. It returns false if an error happens or an invalid option is used ๐Ÿ’…

๐Ÿงฎ let ๐Ÿงฎ

let is the mathy one ๐Ÿค“

let arg [arg ...]

Each arg is an arithmetic expression to be evaluated. (see ARITHMETIC EVALUATION in bash(1) if you want the full scoop ๐Ÿ“š) If the last arg evaluates to 0, let returns 1. Otherwise it returns 0 โœจ

๐ŸŽ€ local ๐ŸŽ€

local keeps your variables in their lane ๐Ÿฆ‹

local [option] [name[=value] ... | - ]

For each argument, a local variable named name gets created and assigned value. The option can be any of the options declare accepts ๐Ÿ’… When local is used inside a function, the variable name gets a visible scope that's limited to that function and its children. Totally contained ๐Ÿซง

If name is -, the set of shell options becomes local to the function where local is called. Shell options changed with the set builtin inside the function get restored to their original values when the function returns. The restore works as if a series of set commands were run to put back the values that were there before the function ๐Ÿ”„

With no operands, local writes a list of local variables to the standard output ๐Ÿ“œ Using local when you're not inside a function is an error, so don't do that ๐Ÿ™ˆ

The return status is 0 unless local is used outside a function, an invalid name is supplied, or name is a readonly variable ๐Ÿ’€

๐Ÿšช logout ๐Ÿšช

logout exits a login shell. bye bye ๐Ÿ‘‹๐ŸŒธ

๐Ÿ“š mapfile ๐Ÿ“š

mapfile and readarray are literally the same thing, just with two names ๐Ÿซถ

mapfile [-d delim] [-n count] [-O origin] [-s count] [-t] [-u fd] [-C
callback] [-c quantum] [array]
readarray [-d delim] [-n count] [-O origin] [-s count] [-t] [-u fd] [-C
callback] [-c quantum] [array]

These read lines from the standard input into the indexed array variable array, or from file descriptor fd if you use the -u option. The variable MAPFILE is the default array ๐Ÿ—‚๏ธ Here are the options:

  • -d โ€” the first character of delim is used to end each input line, instead of newline. If delim is the empty string, mapfile ends a line when it reads a NUL character ๐ŸŒ™
  • -n โ€” copies at most count lines. If count is 0, all lines get copied ๐Ÿ“‹
  • -O โ€” starts assigning to array at index origin. The default index is 0 ๐Ÿ”ข
  • -s โ€” discards the first count lines read ๐Ÿ—‘๏ธ
  • -t โ€” removes a trailing delim (default newline) from each line read โœ‚๏ธ
  • -u โ€” reads lines from file descriptor fd instead of the standard input ๐Ÿ”Œ
  • -C โ€” evaluates callback each time quantum lines are read. The -c option specifies quantum ๐Ÿ”
  • -c โ€” specifies the number of lines read between each call to callback ๐ŸŽฏ

If -C is specified without -c, the default quantum is 5000 ๐Ÿ’… When callback gets evaluated, it's given the index of the next array element to be assigned, plus the line to be assigned to that element, as extra arguments. callback is evaluated after the line is read but before the array element is assigned, so the timing is very precise โฐ

If you don't supply an explicit origin, mapfile clears array before assigning to it. Fresh start, bestie ๐Ÿงผ

mapfile returns successfully unless an invalid option or option argument is supplied, array is invalid or can't be assigned, or array isn't an indexed array ๐Ÿ’€

๐Ÿฅž popd ๐Ÿฅž

popd takes stuff off the directory stack ๐Ÿ“š

popd [-n] [+n] [-n]

The elements are numbered from 0, starting at the first directory listed by dirs ๐Ÿ”ข With no arguments, popd removes the top directory from the stack and changes to the new top directory ๐Ÿšถโ€โ™€๏ธ If you do supply arguments, here's what they do:

  • -n โ€” suppresses the normal change of directory when removing directories from the stack, so only the stack gets messed with ๐Ÿงš
  • +n โ€” removes the *n*th entry counting from the left of the list shown by dirs, starting with zero. For example: "popd +0" removes the first directory, "popd +1" removes the second ๐Ÿฆ‹
  • -n โ€” removes the *n*th entry counting from the right of the list shown by dirs, starting with zero. For example: "popd -0" removes the last directory, "popd -1" removes the next to last ๐Ÿ™ƒ

If the top element of the directory stack gets modified and you didn't use -n, popd uses the cd builtin to change to the directory at the top of the stack. If the cd fails, popd returns a non-zero value ๐Ÿ˜ญ

Otherwise, popd returns false if an invalid option is used, the directory stack is empty, or you point at a non-existent directory stack entry ๐Ÿ’€

If the popd command works, bash runs dirs to show you the final contents of the directory stack, and the return status is 0 โœจ

โœจ printf โœจ

printf [-v var] format [arguments]

okay so printf writes your formatted arguments to the standard output, following the pattern you give it in format. ๐Ÿ’… with -v, it stashes the result into the variable var instead of printing it. ๐ŸŽ€

the format is a string with three kinds of stuff in it: plain characters that get copied straight through, character escape sequences that get converted and copied, and format specifications, each of which grabs the next argument and prints it. ๐Ÿฆ‹ on top of the standard printf(1) specifiers, bash adds these extensions:

  • %b โ€” expands backslash escape sequences in the argument, exactly like echo -e does. ๐ŸŒธ
  • %q โ€” outputs the argument in a form you can paste right back into shell input. ๐Ÿซถ
  • %Q โ€” same as %q, but any precision you gave gets applied to the argument before it gets quoted. ๐Ÿ’œ
  • %(datefmt)T โ€” outputs a date-time string using datefmt as a format string for strftime(3). The argument is an integer counting seconds since the epoch. โœจ there are two special values: -1 means the current time, and -2 means the time the shell was invoked. no argument at all acts like you passed -1. ๐Ÿงš this one is an exception to the usual printf behavior, so keep that in mind, bestie. ๐Ÿ™ˆ

the %b, %q, and %T directives all respect the field width and precision from the format spec. they write that many bytes from the expanded argument (or use that wide a field for it). ngl, that matters because the expanded result usually has more characters than what you started with. ๐Ÿ’€

arguments for the non-string format specifiers are treated as C constants. a leading plus or minus sign is allowed. and if the first character is a single or double quote, the value becomes the ASCII value of the character right after it. ๐Ÿ”ฅ

the format gets reused as many times as needed to eat all the arguments. if the format wants more arguments than you supplied, the extra specs act like they got a zero value or a null string, whichever fits. the return value is 0 on success and non-zero on failure. ๐Ÿ‘‘


โœจ pushd โœจ

pushd [-n] [+n] [-n]
pushd [-n] [dir]

okay this one is giving directory stack queen energy. ๐Ÿ‘‘ pushd either adds a directory to the top of the directory stack or rotates the stack, so the new top becomes your current working directory. with no arguments at all, it just swaps the top two elements of the stack. ๐Ÿฆ‹ here's what the arguments do:

  • -n โ€” skips the usual directory change when you rotate or add stuff, so only the stack gets touched. ๐ŸŒธ
  • +n โ€” rotates the stack so the nth directory (counted from the left of the list dirs shows, starting at zero) ends up on top. ๐Ÿ’…
  • -n โ€” rotates the stack so the nth directory (counted from the right of the dirs list, starting at zero) ends up on top. ๐Ÿ™ˆ yes, it's the same -n spelling as the one above, just counting from the other end. bestie, pay attention. ๐Ÿ˜ญ
  • dir โ€” adds dir to the top of the directory stack. ๐ŸŽ€

once the stack has been changed, if you didn't pass -n, pushd uses the cd builtin to move into whatever directory is now on top. if that cd fails, pushd returns a non-zero value. โœจ

if no arguments are supplied, pushd returns 0 unless the directory stack is empty. when you're rotating, it returns 0 unless the stack is empty or you asked for a stack element that doesn't exist. ๐Ÿ’œ

if pushd succeeds, bash runs dirs to show you the final contents of the directory stack. ๐Ÿงš


โœจ pwd โœจ

pwd [-LP]

pwd prints the absolute pathname of your current working directory. ๐ŸŒˆ the path it prints has no symbolic links in it if you pass -P, or if the -o physical option to the set builtin is turned on. if you use -L, the printed path might still contain symbolic links. ๐Ÿฆ‹

the return status is 0 unless there's an error while reading the name of the current directory, or you pass an invalid option. ๐Ÿซถ


โœจ read โœจ

read [-ers] [-a aname] [-d delim] [-i text] [-n nchars] [-N nchars] [-p
prompt] [-t timeout] [-u fd] [name ...]

okay this is a whole mood. ๐ŸŒธ read grabs one line from standard input, or from the file descriptor you pass to -u. it splits that line into words the same way the shell does for expansion (check Word Splitting in bash(1) for the full tea โ˜•). then the first word goes into the first name, the second word into the second name, and so on. ๐Ÿ’…

if there are more words than names, the leftover words and their in-between delimiters all get dumped into the last name. if there are fewer words than names, the leftover names just get empty values. ๐Ÿ™ˆ

the characters in IFS are what split the line into words, using the same rules the shell uses for expansion. ๐Ÿ”ฅ and the backslash (\) can be used to remove any special meaning from the next character read, and also for line continuation. ๐Ÿซถ here are the options:

  • -a aname โ€” the words go into sequential indices of the array variable aname, starting at 0. aname gets unset before any new values are assigned, and any other name arguments are ignored. ๐Ÿฆ‹
  • -d delim โ€” the first character of delim ends the input line instead of newline. if delim is the empty string, read ends the line when it reads a NUL character. ๐Ÿ’œ
  • -e โ€” if standard input is coming from a terminal, readline (check READLINE in bash(1)) gets used to grab the line. it uses the current editing settings (or the defaults, if line editing wasn't already active), but it uses readline's default filename completion. โœจ
  • -i text โ€” if readline is doing the reading, text gets placed into the editing buffer before you start editing. ๐ŸŒˆ
  • -n nchars โ€” read returns after reading nchars characters instead of waiting for a whole line. but it still honors a delimiter if it hits one before nchars characters are read. ๐Ÿงš
  • -N nchars โ€” read returns after reading exactly nchars characters, unless it hits EOF or times out. delimiter characters in the input don't get special treatment and won't make read return until nchars characters are read. the result isn't split on the characters in IFS. the goal is that the variable gets exactly the characters that were read (except for backslash, which is covered by -r below). ๐ŸŽ€
  • -p prompt โ€” shows prompt on standard error, with no trailing newline, before any input is read. the prompt only shows up if input is coming from a terminal. ๐Ÿ’…
  • -r โ€” backslash stops acting as an escape character and is treated as a regular part of the line. ๐Ÿ™ˆ that also means a backslash-newline pair can't be used for line continuation anymore. ๐Ÿ˜ญ
  • -s โ€” silent mode. if input is coming from a terminal, the characters don't get echoed. ๐Ÿคซ
  • -t timeout โ€” makes read time out and return failure if a full line (or the specified number of characters) isn't read within timeout seconds. timeout can be a decimal number with a fractional part after the decimal point. this option only works when read is reading from a terminal, pipe, or other special file. it does nothing for regular files. if read times out, it saves any partial input into the variable name you gave it. if timeout is 0, read returns right away without trying to read any data. the exit status is 0 if input is available on the file descriptor (or read is going to return EOF), and non-zero otherwise. the exit status is greater than 128 if the timeout gets exceeded. โฐ๐Ÿ’€
  • -u fd โ€” reads input from file descriptor fd. ๐ŸŒธ
if no names are supplied, the line gets read (without the ending delimiter, but otherwise unchanged) and assigned to the variable REPLY. ๐Ÿซถ

the exit status is 0 unless end-of-file is hit, read times out (in which case the status is greater than 128), a variable assignment error happens (like trying to assign to a readonly variable), or you give -u an invalid file descriptor. ๐Ÿ™ˆ


โœจ readonly โœจ

readonly [-aAf] [-p] [name[=word] ...]

readonly marks the given names as readonly, which means their values can't be changed by later assignments. ๐Ÿ”’ if you pass -f, the functions matching the names get marked instead. ๐Ÿฆ‹

the -a option restricts the variables to indexed arrays, and the -A option restricts them to associative arrays. if you use both, -A wins. ๐Ÿ’œ if you don't give any name arguments, or you pass -p, bash prints a list of all the readonly names. the other options can narrow that list down to a subset of the readonly names. โœจ

the -p option prints the output in a format you can reuse as input. ๐Ÿงš if a name is followed by =word, the variable's value gets set to word. ๐ŸŒˆ

the return status is 0 unless you pass an invalid option, one of the names isn't a valid shell variable name, or you pass -f with a name that isn't a function. ๐Ÿ’…

โœจ return [n] โœจ

okay so return is the bestie that makes a function stop running and hand back the value you give it, n, to whoever called it ๐Ÿ’… If you leave n out, the return status is whatever the last command in the function body gave back. ๐Ÿซถ

If return runs inside a trap handler, the status comes from the last command that ran before the trap handler kicked in. If it runs during a DEBUG trap, the status comes from the last command the trap handler ran before return got called. ๐Ÿ™ˆ

Now, if return shows up outside a function but while a script is running through the . (source) command, it stops that script and sends back either n or the exit status of the last command the script ran, as the script's exit status. โœจ

If you give n, only its least significant 8 bits count, so the value gets squished down. ๐Ÿงš

The return status is non-zero if you hand return a non-numeric argument, or if you use it outside a function and not while a script is running through . or source. ๐Ÿ’€

Also, any command tied to the RETURN trap runs before execution picks back up after the function or script. Main character energy, no cap ๐Ÿ‘‘

โœจ set โœจ

Okay this one is a whole vibe ๐ŸŒˆ With no options, set shows you the name and value of every shell variable, formatted so you can copy it back in to set or reset your variables. Read-only variables can't be reset, so don't even try ๐Ÿ˜ญ In posix mode, only shell variables get listed. The output is sorted according to the current locale. ๐ŸŽ€

When you do pass options, they set or unset shell attributes. Whatever is left after the options get processed becomes the values for the positional parameters, assigned in order to $1, $2, ... $n. โœจ

Here's the full synopsis, bestie:

set [-abefhkmnptuvxBCEHPT] [-o option-name] [--] [-] [arg ...]
set [+abefhkmnptuvxBCEHPT] [+o option-name] [--] [-] [arg ...]

And here's what the options mean ๐Ÿฆ‹

  • -a โ€” Every variable or function that gets created or modified is given the export attribute, so it's marked for export to the environment of later commands. Super shareable ๐Ÿ’–
  • -b โ€” Background jobs that have terminated get their status reported right away, instead of waiting until before the next primary prompt. This only works when job control is enabled. ๐Ÿ“
  • -e โ€” Okay, this one is iconic but also a little tricky ๐Ÿ™ˆ The shell exits immediately if a pipeline (which can just be one simple command), a list, or a compound command (check SHELL GRAMMAR in bash(1)) returns a non-zero status. But there are exceptions, babe:
    • The shell does not exit if the failing command is part of the command list right after a while or until keyword.
    • It doesn't exit if the failing command is part of the test after an if or elif reserved word.
    • It doesn't exit if the failing command is part of any command run in a && or || list, except the command after the final && or ||.
    • It doesn't exit for any command in a pipeline except the last one.
    • It doesn't exit if the command's return value is being inverted with !.

If a compound command other than a subshell returns non-zero because a command failed while -e was being ignored, the shell still doesn't exit. A trap on ERR, if you've set one, runs before the shell exits. ๐Ÿซถ This option applies to the shell environment and each subshell environment separately (see COMMAND EXECUTION ENVIRONMENT in bash(1)), so it can make subshells exit before they finish running all their commands. ๐Ÿ˜ญ

Heads up: because -e applies inside subshells too, a subshell can bail out early and skip the rest of its commands. Plan around that or you'll be so confused, fr fr ๐Ÿ’€

If a compound command or shell function runs where -e is being ignored, none of the commands inside its body care about the -e setting, even if -e is on and a command fails. And if a compound command or function flips -e while it's in that ignored context, the change doesn't kick in until the compound command, or the command that called the function, finishes. ๐Ÿ™ˆ

  • -f โ€” Turns off pathname expansion (globbing) ๐Ÿงบ
  • -h โ€” Remembers where commands live as they get looked up for running. This one's already on by default ๐Ÿ—บ๏ธ
  • -k โ€” Every assignment-style argument goes into the environment for a command, not just the ones sitting in front of the command name โœจ
  • -m โ€” Monitor mode, aka job control ๐ŸŽ›๏ธ It's on by default for interactive shells on systems that support it (check JOB CONTROL in bash(1)). Every process gets its own process group. When a background job finishes, the shell prints a line with its exit status.
  • -n โ€” Reads your commands but doesn't actually run them. Super handy for checking a shell script for syntax errors ๐Ÿ” Interactive shells ignore this one.
  • -o option-name โ€” Lets you use long option names. Here's the full menu:
    • allexport โ€” Same as -a.
    • braceexpand โ€” Same as -B.
    • emacs โ€” Gives you an emacs-style command line editing interface ๐Ÿ–Š๏ธ It's on by default when the shell is interactive, unless you start the shell with --noediting. It also changes the editing interface used for read -e.
    • errexit โ€” Same as -e.
    • errtrace โ€” Same as -E.
    • functrace โ€” Same as -T.
    • hashall โ€” Same as -h.
    • histexpand โ€” Same as -H.
    • history โ€” Turns on command history, which you can read about in bash(1) under HISTORY. It's on by default in interactive shells ๐Ÿ“œ
    • ignoreeof โ€” Acts as if you'd run IGNOREEOF=10 (see Shell Variables in bash(1)) ๐Ÿšช
    • keyword โ€” Same as -k.
    • monitor โ€” Same as -m.
    • noclobber โ€” Same as -C.
    • noexec โ€” Same as -n.
    • noglob โ€” Same as -f.
    • nolog โ€” Currently ignored ๐Ÿ˜ถ
    • notify โ€” Same as -b.
    • nounset โ€” Same as -u.
    • onecmd โ€” Same as -t.
    • physical โ€” Same as -P.
    • pipefail โ€” If set, a pipeline's return value is the value of the last (rightmost) command that exited with a non-zero status, or zero if every command in the pipeline succeeded. It's disabled by default ๐Ÿšจ
    • posix โ€” Makes bash behave like the POSIX standard where its default behaviour differs, which is called posix mode. For a reference doc on how posix mode changes things, check SEE ALSO in bash(1) ๐Ÿ“š
    • privileged โ€” Same as -p.
    • verbose โ€” Same as -v.
    • vi โ€” Gives you a vi-style command line editing interface ๐Ÿฆ‹ It also changes the editing interface used for read -e.
    • xtrace โ€” Same as -x.

If you use -o with no option-name, you get the values of the current options printed out. If you use +o with no option-name, you get a series of set commands printed on standard output that would recreate your current option settings ๐Ÿช„

  • -p โ€” Turns on privileged mode ๐Ÿ” In this mode, the $ENV and $BASH_ENV files don't get processed, shell functions don't get inherited from the environment, and the SHELLOPTS, BASHOPTS, CDPATH, and GLOBIGNORE variables get ignored if they show up in the environment. If the shell starts with an effective user (group) id that doesn't match the real user (group) id, and you didn't pass -p, all of this happens and the effective user id gets set to the real user id. If you pass -p at startup, the effective user id doesn't get reset. Turning this option off sets the effective user and group ids to the real user and group ids.
  • -r โ€” Enables restricted shell mode ๐Ÿ”’ > Once this is set, you can't unset it. No takebacks!
  • -t โ€” Exits after reading and executing one command ๐Ÿƒโ€โ™€๏ธ
  • -u โ€” Treats unset variables and parameters as an error during parameter expansion ๐Ÿ’ฅ The exceptions are the special parameters "@" and "*", and array variables subscripted with "@" or "*". If expansion gets attempted on an unset variable or parameter, the shell prints an error message and, if it's not interactive, exits with a non-zero status.
  • -v โ€” Prints shell input lines as they get read ๐Ÿ‘€
  • -x โ€” After expanding each simple command, for command, case command, select command, or arithmetic for command, it displays the expanded value of PS4, followed by the command and its expanded arguments or associated word list ๐Ÿ”Ž
  • -B โ€” The shell does brace expansion (see Brace Expansion in bash(1)). It's on by default ๐Ÿงฉ
  • -C โ€” If set, bash won't overwrite an existing file with the >, >&, and <> redirection operators ๐Ÿ›ก๏ธ You can override this when creating output files by using the >| redirection operator instead of >.
  • -E โ€” If set, any trap on ERR gets inherited by shell functions, command substitutions, and commands run in a subshell environment. Normally the ERR trap doesn't get inherited in those cases ๐Ÿชค
  • -H โ€” Enables ! style history substitution ๐Ÿ“– It's on by default when the shell is interactive.
  • -P โ€” If set, the shell doesn't resolve symbolic links when running commands like cd that change the current working directory. It uses the physical directory structure instead ๐Ÿ—‚๏ธ By default, bash follows the logical chain of directories when it changes the current directory.
  • -T โ€” If set, any traps on DEBUG and RETURN get inherited by shell functions, command substitutions, and commands run in a subshell environment. Normally those DEBUG and RETURN traps don't get inherited in those cases ๐Ÿ•ต๏ธ
  • -- โ€” If no arguments follow this option, the positional parameters get unset. Otherwise, the positional parameters get set to the args, even if some of them start with a - ๐Ÿซถ
  • - โ€” Signals the end of options and makes all remaining args get assigned to the positional parameters. The -x and -v options get turned off. If there are no args, the positional parameters stay unchanged.

The options are off by default unless I've said otherwise ๐Ÿ’… Using + instead of - turns these options off. You can also pass the options as arguments when you invoke the shell. Your current set of options lives in $-. The return status is always true unless you run into an invalid option.


๐ŸŽ€ shift [n]

The positional parameters from n+1 ... get renamed to $1 .... The parameters represented by the numbers $# down to $#-n+1 get unset ๐Ÿซง n has to be a non-negative number that's less than or equal to $#. If n is 0, no parameters change. If you don't give n, it's assumed to be 1. If n is greater than $#, the positional parameters don't change. The return status is greater than zero if n is greater than $# or less than zero, and otherwise it's 0.


๐ŸŒˆ shopt [-pqsu] [-o] [optname ...]

This one toggles the values of settings that control optional shell behaviour โš™๏ธ The settings can be either the ones listed below or, if you use the -o option, the ones available with the -o option to the set builtin. With no options, or with the -p option, you get a list of every settable option, with an indication of whether each one is set. If you supply optnames, the output gets narrowed down to just those options. The -p option shows the output in a form you can reuse as input ๐Ÿ” Here's what the other options do:

  • -s โ€” Enables (sets) each optname โœ…
  • -u โ€” Disables (unsets) each optname โŒ
  • -q โ€” Suppresses normal output (quiet mode) ๐Ÿคซ The return status tells you whether the optname is set or unset. If you give multiple optname arguments with -q, the return status is zero only if all optnames are enabled, and non-zero otherwise.
  • -o โ€” Limits the values of optname to the ones defined for the -o option to the set builtin ๐ŸŽฏ

If you use either -s or -u with no optname arguments, shopt only shows the options that are set or unset, respectively. Unless I say otherwise, the shopt options are disabled (unset) by default ๐Ÿ™…โ€โ™€๏ธ

When you're listing options, the return status is zero if all optnames are enabled, and non-zero otherwise. When you're setting or unsetting options, the return status is zero unless an optname isn't a valid shell option.

The list of shopt options is:

  • assoc_expand_once: okay bestie, when this is set โœจ the shell stops evaluating associative array subscripts more than once during arithmetic expression evaluation, while running builtins that can do variable assignments, and while running builtins that do array dereferencing. ๐Ÿ’…
  • autocd: if set ๐Ÿš—, a command name that is a directory gets run as if you'd typed it as the argument to cd. Only interactive shells use this one ๐ŸŒธ.
  • cdable_vars: if set ๐ŸŽ€, when the argument to cd isn't a directory, the shell assumes it's the name of a variable and goes to whatever directory that variable holds ๐Ÿงš.
  • cdspell: if set ๐Ÿ”, tiny spelling mistakes in a directory name passed to cd get fixed for you. It catches transposed characters, one missing character, and one extra character too many ๐Ÿ™ˆ. When it finds a fix, it prints the corrected filename and then keeps going. Only interactive shells use this one ๐Ÿฆ‹.
  • checkhash: if set ๐Ÿงพ, bash makes sure a command in the hash table still exists before it tries to run it. If the hashed command is gone, it does a normal path search instead ๐Ÿ”„.
  • checkjobs: if set ๐Ÿ’ผ, an interactive shell lists the status of stopped and running jobs before it exits ๐Ÿ‘€. If any jobs are still running, the exit gets postponed until you try to exit a second time with no other command in between (see JOB CONTROL in bash(1)) ๐Ÿ˜ญ. The shell always postpones exiting if any jobs are stopped, no matter what ๐Ÿ›‘.
  • checkwinsize: enabled by default ๐ŸŒˆ. After each external (non-builtin) command, bash checks the window size and, if needed, updates LINES and COLUMNS ๐Ÿ“.
  • cmdhist: enabled by default ๐Ÿ“œ. When set, bash tries to save every line of a multi-line command as one single history entry, which makes re-editing multi-line commands so much easier ๐Ÿฅน. It only does anything if command history is turned on, as described in bash(1) under HISTORY ๐Ÿ’….
  • compat31, compat32, compat40, compat41, compat42, compat43, compat44, compat50: these control the shell's compatibility mode, so the shell can act like older versions ๐Ÿ•ฐ๏ธ (see SHELL COMPATIBILITY MODE in bash(1)) ๐Ÿ’ซ.
  • complete_fullquote: set by default, which is the default bash behavior in versions through 4.2 ๐Ÿง. When set, bash quotes all shell metacharacters in filenames and directory names during completion ๐Ÿ›ก๏ธ. When it's not set, bash drops metacharacters like the dollar sign from the list of characters that get quoted in completed filenames, but only when those show up in shell variable references in the words being completed ๐Ÿคทโ€โ™€๏ธ. So dollar signs in variable names that expand to directories won't get quoted, and dollar signs that show up in filenames won't get quoted either ๐Ÿ˜ฌ. This is only active when bash uses backslashes to quote completed filenames ๐Ÿ™ƒ.
  • direxpand: if set, bash swaps directory names for the results of word expansion during filename completion ๐Ÿช„. Heads up, this changes what's in the readline editing buffer ๐Ÿ“. If it's not set, bash tries to keep whatever you typed ๐Ÿ’–.
  • dirspell: if set, bash tries spelling correction on directory names during word completion when the directory name you gave it doesn't exist ๐Ÿ•ต๏ธโ€โ™€๏ธ.
  • dotglob: if set, bash includes filenames that start with a . in the results of pathname expansion ๐Ÿซฃ. The filenames . and .. always have to be matched explicitly, even when dotglob is set ๐ŸŒฟ.
  • execfail: if set, a non-interactive shell won't exit when it can't execute the file given as an argument to the exec builtin ๐Ÿƒโ€โ™€๏ธ. An interactive shell never exits when exec fails either ๐Ÿ’….
  • expand_aliases: aliases get expanded the way bash(1) describes under ALIASES ๐Ÿชž. It's enabled by default for interactive shells ๐Ÿ’œ.
  • extdebug: okay, this one is a whole vibe ๐Ÿ›. If it's set when the shell starts, or in a shell startup file, it runs the debugger profile before the shell starts, exactly like the --debugger option โœจ. If it's set after invocation, behavior meant for debuggers gets turned on ๐Ÿ”ง:
    1. The -F option to the declare builtin shows the source file name and line number for each function name you pass in as an argument ๐Ÿ“.
    2. If the command run by the DEBUG trap returns a non-zero value, the next command gets skipped and doesn't run ๐Ÿšซ.
    3. If the command run by the DEBUG trap returns a value of 2, and the shell is running in a subroutine (a shell function, or a shell script run by the . or source builtins), the shell pretends it called return ๐Ÿชƒ.
    4. BASH_ARGC and BASH_ARGV get updated the way their descriptions in bash(1)) say ๐Ÿ“‹.
    5. Function tracing is turned on ๐Ÿ”: command substitution, shell functions, and subshells started with ( command ) inherit the DEBUG and RETURN traps ๐ŸŽ€.
    6. Error tracing is turned on too ๐Ÿšจ: command substitution, shell functions, and subshells started with ( command ) inherit the ERR trap ๐Ÿซถ.
  • extglob: if set, the extended pattern matching features described in bash(1) under Pathname Expansion are turned on ๐Ÿงฉ.
  • extquote: enabled by default ๐ŸŒŸ. When set, $'string' and $"string" quoting gets done inside ${parameter} expansions that are wrapped in double quotes ๐Ÿ’ซ.
  • failglob: if set, patterns that don't match any filenames during pathname expansion throw an expansion error instead of sticking around as-is ๐Ÿ’€.
  • force_fignore: enabled by default ๐Ÿ™…โ€โ™€๏ธ. When set, the suffixes listed in the FIGNORE shell variable make words get ignored during word completion, even if the ignored words are the only possible completions ๐Ÿซ . Check out SHELL VARIABLES in bash(1) for the full scoop on FIGNORE ๐Ÿ“–.
  • globasciiranges: if set, range expressions in bracket expressions for pattern matching (see Pattern Matching in bash(1)) act like the traditional C locale when comparing ๐ŸŒ. So the current locale's collating sequence doesn't count, which means b won't sort between A and B, and upper-case and lower-case ASCII characters sort together ๐Ÿ”ค.
  • globskipdots: enabled by default ๐Ÿ™ˆ. Pathname expansion will never match the filenames . and .., even if the pattern starts with a . ๐Ÿšซ.
  • globstar: if set, the pattern ** used in a pathname expansion context matches all files and zero or more directories and subdirectories ๐ŸŒณ. If the pattern is followed by a /, only directories and subdirectories match ๐Ÿ“.
  • gnu_errfmt: if set, shell error messages get written in the standard GNU error message format ๐Ÿงพ.
  • histappend: if set, the history list gets appended to the file named by the HISTFILE variable when the shell exits, instead of overwriting it ๐Ÿ“š.
  • histreedit: if set, and readline is being used, you get the chance to re-edit a failed history substitution ๐Ÿ”.
  • histverify: if set, and readline is being used, the results of history substitution don't get passed straight to the shell parser ๐Ÿ›‘. Instead, the resulting line lands in the readline editing buffer so you can keep tweaking it โœ๏ธ.
  • hostcomplete: enabled by default ๐Ÿ–ฅ๏ธ. If set, and readline is being used, bash tries hostname completion when you're completing a word that contains a @ (see Completing under READLINE in bash(1)) ๐Ÿ’Œ.
  • huponexit: if set, bash sends SIGHUP to all jobs when an interactive login shell exits ๐Ÿ‘‹.
  • inherit_errexit: enabled when posix mode is enabled ๐Ÿง. If set, command substitution inherits the value of the errexit option, instead of unsetting it in the subshell environment ๐Ÿ”’.
  • interactive_comments: enabled by default ๐Ÿ’ฌ. If set, a word starting with # makes that word and everything else on the line get ignored in an interactive shell (see COMMENTS in bash(1)) ๐Ÿคซ.
  • lastpipe: if set, and job control isn't active, the shell runs the last command of a pipeline that isn't run in the background, in the current shell environment ๐Ÿšฐ.
  • lithist: if set, and the cmdhist option is enabled, multi-line commands get saved to history with embedded newlines wherever possible, instead of using semicolon separators ๐Ÿ“.

localvar_inherit ๐ŸŒธ If set, local variables inherit the value and attributes of a variable of the same name that exists at a previous scope before any new value is assigned. The nameref attribute is not inherited. ๐Ÿฆ‹

localvar_unset ๐Ÿงš If set, calling unset on local variables in previous function scopes marks them so subsequent lookups find them unset until that function returns. This is identical to the behavior of unsetting local variables at the current function scope. โœจ

login_shell ๐Ÿ” The shell sets this option if it is started as a login shell (see INVOCATION in bash(1)). The value may not be changed. ๐Ÿ™ˆ

mailwarn ๐Ÿ“ฌ If set, and a file that bash is checking for mail has been accessed since the last time it was checked, the message ``The mail in mailfile has been read'' is displayed. ๐Ÿ’Œ

no_empty_cmd_completion ๐Ÿ™…โ€โ™€๏ธ If set, and readline is being used, bash will not attempt to search the PATH for possible completions when completion is attempted on an empty line. ๐Ÿซถ

nocaseglob ๐ŸŽ€ If set, bash matches filenames in a case-insensitive fashion when performing pathname expansion (see Pathname Expansion in bash(1)). No more "why won't it find my file" moments, bestie ๐Ÿ’…

nocasematch ๐ŸŒˆ If set, bash matches patterns in a case-insensitive fashion when performing matching while executing case or [[ conditional commands, when performing pattern substitution word expansions, or when filtering possible completions as part of programmable completion. Literally case-insensitive everywhere it counts โœจ

noexpand_translation ๐Ÿ”ฎ If set, bash encloses the translated results of $"..." quoting in single quotes instead of double quotes. If the string is not translated, this has no effect. ๐Ÿ’œ

nullglob ๐Ÿซง If set, bash allows patterns which match no files (see Pathname Expansion in bash(1)) to expand to a null string, rather than themselves. So a pattern with zero matches just vanishes, it's giving disappearing act ๐Ÿช„

patsub_replacement โญ If set, bash expands occurrences of & in the replacement string of pattern substitution to the text matched by the pattern, as described under Parameter Expansion in bash(1). This option is enabled by default. The & slay is real ๐Ÿ”ฅ

progcomp ๐Ÿง If set, the programmable completion facilities (see Programmable Completion in bash(1)) are enabled. This option is enabled by default. ๐ŸŒŸ

progcomp_alias ๐Ÿญ If set, and programmable completion is enabled, bash treats a command name that doesn't have any completions as a possible alias and attempts alias expansion. If it has an alias, bash attempts programmable completion using the command word resulting from the expanded alias. Alias glow-up, no cap ๐Ÿ’–

promptvars ๐ŸŽจ If set, prompt strings undergo parameter expansion, command substitution, arithmetic expansion, and quote removal after being expanded as described in PROMPTING in bash(1). This option is enabled by default. Your prompt is about to get so extra ๐Ÿ’…โœจ

restricted_shell ๐Ÿšซ The shell sets this option if it is started in restricted mode (see RESTRICTED SHELL in bash(1)). The value may not be changed. This is not reset when the startup files are executed, allowing the startup files to discover whether or not a shell is restricted. So the startup files can check if they're stuck in restricted mode, lowkey genius design ๐Ÿ”’

shift_verbose ๐Ÿ“ฃ If set, the shift builtin prints an error message when the shift count exceeds the number of positional parameters. No silent failures on my watch ๐Ÿ˜ค

sourcepath ๐Ÿ—บ๏ธ If set, the . (source) builtin uses the value of PATH to find the directory containing the file supplied as an argument. This option is enabled by default. ๐Ÿฆ‹

varredir_close ๐ŸŒฟ If set, the shell automatically closes file descriptors assigned using the {varname} redirection syntax (see REDIRECTION in bash(1)) instead of leaving them open when the command completes. Tidy shell, tidy life ๐Ÿงน๐Ÿ’š

xpg_echo ๐ŸŒป If set, the echo builtin expands backslash-escape sequences by default. ๐Ÿ‹


โœจ suspend [-f]

Suspend the execution of this shell until it receives a SIGCONT signal. Okay so, a login shell, or a shell without job control enabled, cannot be suspended ๐Ÿ™…โ€โ™€๏ธ but the -f option can be used to override this and force the suspension. Main character move ๐Ÿ˜ค The return status is 0 unless the shell is a login shell or job control is not enabled and -f is not supplied. ๐Ÿ“Š

๐Ÿงš test expr / [ expr ]

Return a status of 0 (true) or 1 (false) depending on the evaluation of the conditional expression expr. Each operator and operand must be a separate argument. Expressions are composed of the primaries described in bash(1) under CONDITIONAL EXPRESSIONS. test does not accept any options, nor does it accept and ignore an argument of -- as signifying the end of options. No options for test, it's giving minimalism ๐Ÿค

Expressions may be combined using the following operators, listed in decreasing order of precedence. The evaluation depends on the number of arguments; see below. Operator precedence is used when there are five or more arguments. ๐Ÿ’…

  • ! expr โ€” True if expr is false. ๐Ÿ™ƒ
  • ( expr ) โ€” Returns the value of expr. This may be used to override the normal precedence of operators. ๐ŸŽ€
  • expr1 -a expr2 โ€” True if both expr1 and expr2 are true. ๐Ÿซถ
  • expr1 -o expr2 โ€” True if either expr1 or expr2 is true. ๐ŸŒˆ

test and [ evaluate conditional expressions using a set of rules based on the number of arguments. Bestie, pay attention to this part, it's the whole vibe ๐Ÿ‘€

๐ŸŒธ 0 arguments

The expression is false. Nothing, nada, zilch ๐Ÿ’€

๐ŸŒธ 1 argument

The expression is true if and only if the argument is not null. ๐Ÿ’–

๐ŸŒธ 2 arguments

If the first argument is !, the expression is true if and only if the second argument is null. If the first argument is one of the unary conditional operators listed in bash(1) under CONDITIONAL EXPRESSIONS, the expression is true if the unary test is true. If the first argument is not a valid unary conditional operator, the expression is false. ๐Ÿง

๐ŸŒธ 3 arguments

The following conditions are applied in the order listed. If the second argument is one of the binary conditional operators listed in bash(1) under CONDITIONAL EXPRESSIONS, the result of the expression is the result of the binary test using the first and third arguments as operands. The -a and -o operators are considered binary operators when there are three arguments. If the first argument is !, the value is the negation of the two-argument test using the second and third arguments. If the first argument is exactly ( and the third argument is exactly ), the result is the one-argument test of the second argument. Otherwise, the expression is false. ๐Ÿฆ‹

๐ŸŒธ 4 arguments

The following conditions are applied in the order listed. If the first argument is !, the result is the negation of the three-argument expression composed of the remaining arguments. the two-argument test using the second and third arguments. If the first argument is exactly ( and the fourth argument is exactly ), the result is the two-argument test of the second and third arguments. Otherwise, the expression is parsed and evaluated according to precedence using the rules listed above. ๐Ÿคฏ

๐ŸŒธ 5 or more arguments

The expression is parsed and evaluated according to precedence using the rules listed above. ๐Ÿงฎ

When used with test or [, the < and > operators sort lexicographically using ASCII ordering. ๐Ÿ”คโœจ

โฑ๏ธ times

Print the accumulated user and system times for the shell and for processes run from the shell. The return status is 0. โฐ

๐Ÿชค trap [-lp] [[arg] sigspec ...]

The command arg is to be read and executed when the shell receives signal(s) sigspec. If arg is absent (and there is a single sigspec) or -, each specified signal is reset to its original disposition (the value it had upon entrance to the shell). If arg is the null string the signal specified by each sigspec is ignored by the shell and by the commands it invokes. If arg is not present and -p has been supplied, then the trap commands associated with each sigspec are displayed. If no arguments are supplied or if only -p is given, trap prints the list of commands associated with each signal. The -l option causes the shell to print a list of signal names and their corresponding numbers. Each sigspec is either a signal name defined in <signal.h>, or a signal number. Signal names are case insensitive and the SIG prefix is optional. Trap-ped and ready to go ๐Ÿชค๐Ÿ’…

If a sigspec is EXIT (0) the command arg is executed on exit from the shell. If a sigspec is DEBUG, the command arg is executed before every simple command, for command, case command, select command, every arithmetic for command, and before the first command executes in a shell function (see SHELL GRAMMAR in bash(1)). Refer to the description of the extdebug option to the shopt builtin for details of its effect on the DEBUG trap. ๐Ÿ› If a sigspec is RETURN, the command arg is executed each time a shell function or a script executed with the . or source builtins finishes executing. ๐Ÿ”

The ERR trap is the one that skips the same cases as errexit, and that's a whole mood. ๐Ÿ’…

Signals that were ignored when the shell started can't be trapped or reset, no cap. ๐Ÿ™ˆ Trapped signals that aren't ignored get reset to their original values in a subshell or subshell environment whenever one is created. The return status is false if any sigspec is invalid, otherwise trap returns true. โœจ

๐Ÿฆ‹ type

type [-aftpP] name [name ...]

With no options, type tells you how each name would be interpreted if you used it as a command name. Bestie, it's giving detective. ๐Ÿ”

  • With -t, type prints one word: alias, keyword, function, builtin, or file, depending on whether name is an alias, a shell reserved word, a function, a builtin, or a disk file. If the name isn't found, nothing gets printed and the exit status is false. ๐Ÿซถ
  • With -p, type returns the name of the disk file that would run if name were used as a command name. If type -t name wouldn't return file, you get nothing back.
  • -P forces a PATH search for each name, even when type -t name wouldn't return file.
  • If a command is hashed, -p and -P print the hashed value, which is not necessarily the file that shows up first in PATH. Plot twist. ๐Ÿ˜ญ
  • With -a, type prints every place that holds an executable named name. This includes aliases and functions, but only if -p isn't also used. The hashed command table is ignored when you use -a.
  • -f skips shell function lookup, same as the command builtin does.

type returns true if every argument is found and false if any of them aren't. ๐ŸŒธ

๐ŸŒˆ ulimit

ulimit [-HS] -a
ulimit [-HS] [-bcdefiklmnpqrstuvxPRT [limit]]

ulimit gives you control over the resources available to the shell and to the processes it starts, on systems that allow that. Main character energy. ๐Ÿ‘‘

  • -H and -S say whether you're setting the hard or the soft limit for the resource. Once a hard limit is set, a non-root user can't raise it. A soft limit can go up to the hard limit's value. ๐Ÿ”ฅ
  • If you use neither -H nor -S, both the soft and hard limits get set.
  • limit can be a number in the unit for that resource, or one of the special values hard, soft, or unlimited. Those mean the current hard limit, the current soft limit, and no limit, respectively. โœจ
  • If you leave out limit, the current soft limit of the resource gets printed, unless you've given -H.
  • If you ask about more than one resource, the limit name and unit (when it applies) get printed before each value. ๐Ÿงš

The other options work like this:

  • -a โ€” reports every current limit. Nothing gets set. ๐Ÿ’œ
  • -b โ€” the maximum socket buffer size ๐Ÿฆ‹
  • -c โ€” the maximum size of core files created ๐ŸŒธ
  • -d โ€” the maximum size of a process's data segment ๐Ÿ“
  • -e โ€” the maximum scheduling priority, aka "nice" ๐Ÿ’…
  • -f โ€” the maximum size of files written by the shell and its children ๐ŸŽ€
  • -i โ€” the maximum number of pending signals โญ
  • -k โ€” the maximum number of kqueues that may be allocated ๐ŸŒˆ
  • -l โ€” the maximum size that may be locked into memory ๐Ÿ”’
  • -m โ€” the maximum resident set size. Heads up, lots of systems don't honor this one. ๐Ÿ™ˆ
  • -n โ€” the maximum number of open file descriptors. Most systems won't let you set this value. ๐Ÿ˜ญ
  • -p โ€” the pipe size in 512-byte blocks. This one may not be settable. ๐Ÿซถ
  • -q โ€” the maximum number of bytes in POSIX message queues ๐Ÿ’Œ
  • -r โ€” the maximum real-time scheduling priority โšก
  • -s โ€” the maximum stack size ๐Ÿฅž
  • -t โ€” the maximum amount of CPU time, in seconds โฐ
  • -u โ€” the maximum number of processes available to a single user ๐Ÿ‘ฏ
  • -v โ€” the maximum amount of virtual memory available to the shell and, on some systems, to its children ๐ŸŒŠ
  • -x โ€” the maximum number of file locks ๐Ÿ—๏ธ
  • -P โ€” the maximum number of pseudoterminals ๐Ÿ–ฅ๏ธ
  • -R โ€” the maximum time a real-time process can run before blocking, in microseconds ๐Ÿ•ฐ๏ธ
  • -T โ€” the maximum number of threads ๐Ÿงต

If you give limit and skip -a, limit becomes the new value for the resource you picked. If you don't give an option at all, -f is assumed. ๐ŸŽ€

Here's the unit situation, so pay attention bestie. Values are in 1024-byte increments, except:

  • -t is in seconds.
  • -R is in microseconds.
  • -p is in 512-byte blocks.
  • -P, -T, -b, -k, -n, and -u are unscaled values.
  • When the shell is in posix mode, -c and -f are in 512-byte increments instead. ๐Ÿคฏ

The return status is 0 unless you pass an invalid option or argument, or an error happens while a new limit is being set. ๐Ÿ’€

๐Ÿง umask

umask [-p] [-S] [mode]

This sets the user file-creation mask to mode. If mode starts with a digit, it's read as an octal number. Otherwise it's read as a symbolic mode mask, similar to what chmod(1) accepts. ๐ŸŒท

  • If you leave out mode, the current mask gets printed.
  • -S prints the mask in symbolic form. By default the output is an octal number. ๐Ÿฆ„
  • If you give -p and leave out mode, the output comes out in a form you can reuse as input. โ™ป๏ธ

The return status is 0 if the mode was changed successfully or if no mode argument was given. Otherwise it's false. โœจ

๐Ÿ—‘๏ธ unalias

unalias [-a] [name ...]

This removes each name from the list of defined aliases. If you pass -a, every alias definition gets removed, all of them, gone. ๐Ÿซ 

The return value is true unless one of the names you gave isn't a defined alias. ๐Ÿ’œ

๐Ÿซง unset

unset [-fv] [-n] [name ...]

For each name, unset removes the matching variable or function. ๐Ÿงน

  • -v means each name is a shell variable, and that variable gets removed. Read-only variables can't be unset, sorry not sorry. ๐Ÿ”’
  • -f means each name is a shell function, and its function definition gets removed.
  • -n says that if name is a variable with the nameref attribute, the thing that gets unset is name itself, not the variable it points to. -n does nothing if you also pass -f. ๐Ÿ”—
  • With no options, each name is treated as a variable. If there's no variable by that name, a function with that name gets unset instead, if one exists.

Each unset variable or function also gets removed from the environment passed to later commands. ๐ŸŒ

โš ๏ธ Special variables lose their special properties once they're unset, and that sticks even if you set them again later. The full list is: BASH_ALIASES, BASH_ARGV0, BASH_CMDS, BASH_COMMAND, BASH_SUBSHELL, BASHPID, COMP_WORDBREAKS, DIRSTACK, EPOCHREALTIME, EPOCHSECONDS, FUNCNAME, GROUPS, HISTCMD, LINENO, RANDOM, SECONDS, and SRANDOM. ๐Ÿ˜ฑ

The exit status is true unless a name is readonly or can't be unset. ๐Ÿ’…

๐Ÿ•ฐ๏ธ wait

wait [-fn] [-p varname] [id ...]

wait waits for each specified child process and returns its termination status. Each id can be a process ID or a job specification. If you pass a job spec, every process in that job's pipeline gets waited for. ๐Ÿซถ

  • If you don't give any id, wait waits for all running background jobs. It also waits for the last-executed process substitution, if its process ID matches $!, and then the return status is zero. ๐ŸŒˆ
  • With -n, wait waits for a single job from the list of ids. If you didn't supply any ids, it waits for any job to finish, then returns that job's exit status. โณ
  • If none of the arguments you gave is a child of the shell, or if you gave no arguments and the shell has no unwaited-for children, the exit status is 127. ๐Ÿ’€
  • With -p, the process or job identifier of the job whose exit status got returned gets assigned to the variable varname that you name in the option argument. That variable is unset first, before any assignment happens. This only matters when -n is supplied. ๐Ÿงš
  • When job control is enabled, -f makes wait hold on until id terminates before returning its status. Otherwise it returns as soon as the status changes. ๐Ÿ”ฅ
  • If id points at a process or job that doesn't exist, the return status is 127. ๐Ÿ™ˆ
  • If a signal interrupts wait, the return status will be greater than 128, as described under SIGNALS in bash(1). โšก
  • Otherwise, the return status is the exit status of the last process or job that got waited for. ๐ŸŽ€

โœจ SHELL COMPATIBILITY MODE โœจ

okay so bash-4.0 dropped the concept of a shell compatibility level ๐ŸŽ€ you pick it with options to the shopt builtin, like compat31, compat32, compat40, compat41, and so on. there's only one current compatibility level at a time, and each option is mutually exclusive, so you can't stack them ๐Ÿ™…โ€โ™€๏ธ the whole point is to let you keep behavior from older versions that clashes with newer ones while you migrate your scripts to the current features. it's meant to be a temporary fix, bestie, not a forever home ๐Ÿฅน

this section doesn't list behavior that's already standard for a particular version. for example, setting compat32 means quoting the rhs of the regexp matching operator quotes special regexp characters in the word, and that's the default in bash-3.2 and later anyway ๐Ÿ’…

if you enable, say, compat32, it can also change the behavior of every other compatibility level up to and including the current one ๐ŸŒŠ each level controls stuff that changed in that version, but that stuff might have already existed in earlier versions. like, the switch to locale-based comparisons with the [[ command happened in bash-4.1, and earlier versions used ASCII-based comparisons, so enabling compat32 turns on ASCII-based comparisons too. that granularity might not be enough for everything, so use compatibility levels carefully ๐Ÿซถ read the docs for the specific feature to see how it currently behaves.

bash-4.3 introduced a new shell variable called BASH_COMPAT ๐ŸŒธ whatever you assign to it sets the compatibility level. you can use a decimal version number like 4.2, or an integer that matches the compatNN option, like 42.

starting with bash-4.4, bash has started deprecating the older compatibility levels ๐Ÿ‘€ eventually the options get removed in favor of BASH_COMPAT.

bash-5.0 is the last version that gets an individual shopt option for the previous version ๐Ÿ˜ญ from bash-5.0 onward, use BASH_COMPAT.

the table below describes the behavior changes each compatibility level controls. the compatNN tag is shorthand for setting the level to NN through one of these mechanisms. before bash-5.0, you can set the level with the matching compatNN shopt option. for bash-4.3 and later, BASH_COMPAT is the preferred way, and it's required for bash-5.1 and later ๐Ÿ’–


โœจ compat31 โœจ

  • quoting the rhs of the [[ command's regexp matching operator (=~) has no special effect ๐Ÿ™ˆ

โœจ compat32 โœจ

  • interrupting a command list such as "a ; b ; c" causes the execution of the next command in the list. in bash-4.0 and later, the shell acts as if it received the interrupt, so interrupting one command in a list aborts the whole list ๐Ÿ’€

โœจ compat40 โœจ

  • the < and > operators to the [[ command don't consider the current locale when comparing strings. they use ASCII ordering. bash versions before bash-4.1 used ASCII collation and strcmp(3), while bash-4.1 and later use the current locale's collation sequence and strcoll(3) ๐ŸŒˆ

โœจ compat41 โœจ

  • in posix mode, time can be followed by options and still be recognized as a reserved word. this is POSIX interpretation 267 ๐Ÿงš
  • in posix mode, the parser requires an even number of single quotes in the word portion of a double-quoted parameter expansion, and it treats them specially, so characters inside the single quotes count as quoted. this is POSIX interpretation 221 ๐Ÿ“

โœจ compat42 โœจ

  • the replacement string in double-quoted pattern substitution doesn't undergo quote removal, unlike in versions after bash-4.2 ๐Ÿซ 
  • in posix mode, single quotes are special when expanding the word portion of a double-quoted parameter expansion, and they can quote a closing brace or other special character. this is part of POSIX interpretation 221. in later versions, single quotes aren't special inside double-quoted word expansions ๐ŸŽ€

โœจ compat43 โœจ

  • the shell doesn't print a warning if you use a quoted compound assignment as an argument to declare (e.g., declare -a foo='(1 2)'). later versions warn that this usage is deprecated โš ๏ธ
  • word expansion errors count as non-fatal errors that make the current command fail, even in posix mode. the default is to treat them as fatal, making the shell exit ๐Ÿ˜ค
  • when running a shell function, the loop state (while/until/etc.) isn't reset, so break or continue inside that function breaks or continues loops in the calling context. bash-4.4 and later reset the loop state to prevent this ๐Ÿ™…โ€โ™€๏ธ

โœจ compat44 โœจ

  • the shell sets up the values used by BASH_ARGV and BASH_ARGC so they can expand to the shell's positional parameters, even when extended debugging mode isn't enabled ๐Ÿ”ฅ
  • a subshell inherits loops from its parent context, so break or continue makes the subshell exit. bash-5.0 and later reset the loop state to stop that exit ๐Ÿงƒ
  • variable assignments before builtins like export and readonly that set attributes keep affecting variables with the same name in the calling environment, even when the shell isn't in posix mode ๐Ÿ’œ

โœจ compat50 โœจ

  • bash-5.1 changed how $RANDOM is generated to add a bit more randomness. if the compatibility level is 50 or lower, it goes back to the bash-5.0 and earlier method. so seeding the generator by assigning a value to RANDOM gives the same sequence as in bash-5.0 ๐ŸŽฒ
  • if the command hash table is empty, bash versions before bash-5.1 printed an informational message saying so, even when the output could be reused as input. bash-5.1 suppresses that message when the -l option is supplied ๐ŸŒธ

โœจ compat51 โœจ

  • the unset builtin handles attempts to unset the array subscripts @ and * differently depending on whether the array is indexed or associative. it's also different from previous versions ๐Ÿฆ‹

โœจ SEE ALSO โœจ

bash(1), sh(1) ๐Ÿซถ


Okay bestie that's the whole page! ๐ŸŽ€ it's from GNU Bash-2.05a, dated 2001 October 29, and it lives in BASH-BUILTINS(7) ๐Ÿ’…๐ŸŒˆ

๐Ÿ“ฆ where this page comes from