- It\'s FAQ 1 for a reason.
diff --git a/docs/commands/builtin/printf.md b/docs/commands/builtin/printf.md
new file mode 100644
index 0000000..422210c
--- /dev/null
+++ b/docs/commands/builtin/printf.md
@@ -0,0 +1,476 @@
+# The printf command
+
+\ FIXME Stranger, this is a very big
+topic that needs experience - please fill in missing information, extend
+the descriptions, and correct the details if you can! \
\ [**Attention:**]{.underline} This is about the
+Bash-builtin command `printf` - however, the description should be
+nearly identical for an external command that follows POSIX(r).
+
+[GNU Awk](http://www.gnu.org/software/gawk/manual/gawk.html#Printf)
+expects a comma after the format string and between each of the
+arguments of a **printf** command. For examples, see: [code
+snippet](printf?using_printf_inside_of_awk). \
+
+Unlike other documentations, I don\'t want to redirect you to the manual
+page for the `printf()` C function family. However, if you\'re more
+experienced, that should be the most detailed description for the format
+strings and modifiers.
+
+Due to conflicting historical implementations of the `echo` command,
+POSIX(r) recommends that `printf` is preferred over `echo`.
+
+## General
+
+The `printf` command provides a method to print preformatted text
+similar to the `printf()` system interface (C function). It\'s meant as
+successor for `echo` and has far more features and possibilities.
+
+Beside other reasons, POSIX(r) has a very good argument to recommend it:
+Both historical main flavours of the `echo` command are mutual
+exclusive, they collide. A \"new\" command had to be invented to solve
+the issue.
+
+## Syntax
+
+ printf
+
+The text format is given in ``, while all arguments the
+formatstring may point to are given after that, here, indicated by
+``.
+
+Thus, a typical `printf`-call looks like:
+
+ printf "Surname: %s\nName: %s\n" "$SURNAME" "$FIRSTNAME"
+
+where `"Surname: %s\nName: %s\n"` is the format specification, and the
+two variables are passed as arguments, the `%s` in the formatstring
+points to (for every format specifier you give, `printf` awaits one
+argument!).
+
+### Options
+
+ ---------- -------------------------------------------------------------------------------------------------------------------------------
+ `-v VAR` If given, the output is assigned to the variable `VAR` instead of printed to `stdout` (comparable to `sprintf()` in some way)
+ ---------- -------------------------------------------------------------------------------------------------------------------------------
+
+The `-v` Option can\'t assign directly to array indexes in Bash versions
+older than Bash 4.1.
+
+\ In versions newer than 4.1, one must be careful when
+performing expansions into the first non-option argument of printf as
+this opens up the possibility of an easy code injection vulnerability.
+
+ $ var='-vx[$(echo hi >&2)]'; printf "$var" hi; declare -p x
+ hi
+ declare -a x='([0]="hi")'
+
+\...where the echo can of course be replaced with any arbitrary command.
+If you must, either specify a hard-coded format string or use \-- to
+signal the end of options. The exact same issue also applies to
+[read](commands/builtin/read), and a similar one to
+[mapfile](commands/builtin/mapfile), though performing expansions into
+their arguments is less common. \
+
+### Arguments
+
+Of course in shell-meaning the arguments are just strings, however, the
+common C-notations plus some additions for number-constants are
+recognized to give a number-argument to `printf`:
+
+ Number-Format Description
+ --------------- ------------------------------------------------------------------------------------------------------------------------
+ `N` A normal decimal number
+ `0N` An octal number
+ `0xN` A hexadecimal number
+ `0XN` A hexadecimal number
+ `"X` (a literal double-quote infront of a character): interpreted as number (underlying codeset) **don\'t forget escaping**
+ `'X` (a literal single-quote infront of a character): interpreted as number (underlying codeset) **don\'t forget escaping**
+
+[**If more arguments than format specifiers**]{.underline} are present,
+then the format string is re-used until the last argument is
+interpreted. If fewer format specifiers than arguments are present, then
+number-formats are set to zero, while string-formats are set to null
+(empty).
+
+Take care to avoid [word splitting](/syntax/expansion/wordsplit), as
+accidentally passing the wrong number of arguments can produce wildly
+different and unexpected results. See [this article](/syntax/words).
+
+\ [**Again, attention:**]{.underline} When a numerical
+format expects a number, the internal `printf`-command will use the
+common Bash arithmetic rules regarding the base. A command like the
+following example **will** throw an error, since `08` is not a valid
+octal number (`00` to `07`!):
+
+ printf '%d\n' 08
+
+\
+
+### Format strings
+
+The format string interpretion is derived from the C `printf()` function
+family. Only format specifiers that end in one of the letters
+`diouxXfeEgGaAcs` are recognized.
+
+To print a literal `%` (percent-sign), use `%%` in the format string.
+
+[**Again:**]{.underline} Every format specifier expects an associated
+argument provided!
+
+These specifiers have different names, depending who you ask. But they
+all mean the same: A placeholder for data with a specified format:
+
+- format placeholder
+- conversion specification
+- formatting token
+- \...
+
+ Format Description
+ -------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ `%b` Print the associated argument while interpreting backslash escapes in there
+ `%q` Print the associated argument **shell-quoted**, reusable as input
+ `%d` Print the associated argument as **signed decimal** number
+ `%i` Same as `%d`
+ `%o` Print the associated argument as **unsigned octal** number
+ `%u` Print the associated argument as **unsigned decimal** number
+ `%x` Print the associated argument as **unsigned hexadecimal** number with lower-case hex-digits (a-f)
+ `%X` Same as `%x`, but with upper-case hex-digits (A-F)
+ `%f` Interpret and print the associated argument as **floating point** number
+ `%e` Interpret the associated argument as **double**, and print it in `±e` format
+ `%E` Same as `%e`, but with an upper-case `E` in the printed format
+ `%g` Interprets the associated argument as **double**, but prints it like `%f` or `%e`
+ `%G` Same as `%g`, but print it like `%E`
+ `%c` Interprets the associated argument as **char**: only the first character of a given argument is printed
+ `%s` Interprets the associated argument literally as string
+ `%n` Assigns the number of characters printed so far to the variable named in the corresponding argument. Can\'t specify an array index. If the given name is already an array, the value is assigned to the zeroth element.
+ `%a` Interprets the associated argument as **double**, and prints it in the form of a C99 [hexadecimal floating-point literal](http://www.exploringbinary.com/hexadecimal-floating-point-constants/).
+ `%A` Same as `%a`, but print it like `%E`
+ `%(FORMAT)T` output the date-time string resulting from using `FORMAT` as a format string for `strftime(3)`. The associated argument is the number of seconds since Epoch, or `-1` (current time) or `-2` (shell startup time). If no corresponding argument is supplies, the current time is used as default
+ `%%` No conversion is done. Produces a `%` (percent sign)
+
+Some of the mentioned format specifiers can modify their behaviour by
+getting a format modifier:
+
+### Modifiers
+
+To be more flexible in the output of numbers and strings, the `printf`
+command allows format modifiers. These are specified **between** the
+introductory `%` and the character that specifies the format:
+
+ printf "%50s\n" "This field is 50 characters wide..."
+
+#### Field and printing modifiers
+
+ Field output format
+ --------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ `` **Any number**: Specifies a **minimum field width**, if the text to print is shorter, it\'s padded with spaces, if the text is longer, the field is expanded
+ `.` **The dot**: Together with a field width, the field is **not** expanded when the text is longer, the text is truncated instead. \"`%.s`\" is an undocumented equivalent for \"`%.0s`\", which will force a field width of zero, effectively hiding the field from output
+ `*` **The asterisk**: the width is given as argument before the string or number. Usage (the \"`*`\" corresponds to the \"`20`\"): `printf "%*s\n" 20 "test string"`
+ `#` \"Alternative format\" for numbers: see table below
+ `-` **Left-bound** text printing in the field (standard is **right-bound**)
+ `0` Pads numbers with zeros, not spaces
+ `` Pad a positive number with a space, where a minus (`-`) is for negative numbers
+ `+` Prints all numbers **signed** (`+` for positive, `-` for negative)
+ `'` For decimal conversions, the thousands grouping separator is applied to the integer portion of the output according to the current LC_NUMERIC
+
+[**The \"alternative format\" modifier `#`:**]{.underline}
+
+ Alternative Format
+ -------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------
+ `%#o` The octal number is printed with a leading zero, unless it\'s zero itself
+ `%#x`, `%#X` The hex number is printed with a leading \"`0x`\"/\"`0X`\", unless it\'s zero
+ `%#g`, `%#G` The float number is printed with **trailing zeros** until the number of digits for the current precision is reached (usually trailing zeros are not printed)
+ all number formats except `%d`, `%o`, `%x`, `%X` Always print a decimal point in the output, even if no digits follow it
+
+#### Precision
+
+The precision for a floating- or double-number can be specified by using
+`.`, where `` is the number of digits for precision. If
+`` is an asterisk (`*`), the precision is read from the argument
+that precedes the number to print, like (prints 4,3000000000):
+
+ printf "%.*f\n" 10 4,3
+
+The format `.*N` to specify the N\'th argument for precision does not
+work in Bash.
+
+For strings, the precision specifies the maximum number of characters to
+print (i.e., the maximum field width). For integers, it specifies the
+number of digits to print (zero-padding!).
+
+### Escape codes
+
+These are interpreted if used anywhere in the format string, or in an
+argument corresponding to a `%b` format.
+
+ Code Description
+ ---------------- ---------------------------------------------------------------------------------------------------------------------------
+ `\\` Prints the character `\` (backslash)
+ `\a` Prints the alert character (ASCII code 7 decimal)
+ `\b` Prints a backspace
+ `\f` Prints a form-feed
+ `\n` Prints a newline
+ `\r` Prints a carriage-return
+ `\t` Prints a horizontal tabulator
+ `\v` Prints a vertical tabulator
+ `\"` Prints a `'`
+ `\?` Prints a `?`
+ `\` Interprets `` as **octal** number and prints the corresponding character from the character set
+ `\0` same as `\`
+ `\x` Interprets `` as **hexadecimal** number and prints the corresponding character from the character set (**3 digits**)
+ `\u` same as `\x`, but **4 digits**
+ `\U` same as `\x`, but **8 digits**
+
+The following additional escape and extra rules apply only to arguments
+associated with a `%b` format:
+
+ ------ -------------------------------------------------------------------------------------------------------------------------------------------------------------
+ `\c` Terminate output similarly to the `\c` escape used by `echo -e`. printf produces no additional output after coming across a `\c` escape in a `%b` argument.
+ ------ -------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+- Backslashes in the escapes: `\'`, `\"`, and `\?` are not removed.
+- Octal escapes beginning with `\0` may contain up to four digits.
+ (POSIX specifies up to three).
+
+These are also respects in which `%b` differs from the escapes used by
+[\$\'\...\'](syntax/quoting#ansi_c_like_strings) style quoting.
+
+## Examples
+
+### Snipplets
+
+- print the decimal representation of a hexadecimal number (preserve
+ the sign)
+ - `printf "%d\n" 0x41`
+ - `printf "%d\n" -0x41`
+ - `printf "%+d\n" 0x41`
+- print the octal representation of a decimal number
+ - `printf "%o\n" 65`
+ - `printf "%05o\n" 65` (5 characters width, padded with zeros)
+- this prints a 0, since no argument is specified
+ - `printf "%d\n"`
+- print the code number of the character `A`
+ - `printf "%d\n" \'A`
+ - `printf "%d\n" "'A"`
+- Generate a greeting banner and assign it to the variable `GREETER`
+ - `printf -v GREETER "Hello %s" "$LOGNAME"`
+- Print a text at the end of the line, using `tput` to get the current
+ line width
+ - `printf "%*s\n" $(tput cols) "Hello world!"`
+
+### Small code table
+
+This small loop prints all numbers from 0 to 127 in
+
+- decimal
+- octal
+- hex
+
+```{=html}
+
+```
+ for ((x=0; x <= 127; x++)); do
+ printf '%3d | %04o | 0x%02x\n' "$x" "$x" "$x"
+ done
+
+### Ensure well-formatted MAC address
+
+This code here will take a common MAC address and rewrite it into a
+well-known format (regarding leading zeros or upper/lowercase of the hex
+digits, \...):
+
+ the_mac="0:13:ce:7:7a:ad"
+
+ # lowercase hex digits
+ the_mac="$(printf "%02x:%02x:%02x:%02x:%02x:%02x" 0x${the_mac//:/ 0x})"
+
+ # or the uppercase-digits variant
+ the_mac="$(printf "%02X:%02X:%02X:%02X:%02X:%02X" 0x${the_mac//:/ 0x})"
+
+### Replacement echo
+
+This code was found in Solaris manpage for echo(1).
+
+Solaris version of `/usr/bin/echo` is equivalent to:
+
+ printf "%b\n" "$*"
+
+Solaris `/usr/ucb/echo` is equivalent to:
+
+ if [ "X$1" = "X-n" ]
+ then
+ shift
+ printf "%s" "$*"
+ else
+ printf "%s\n" "$*"
+ fi
+
+### prargs Implementation
+
+Working off the replacement echo, here is a terse implementation of
+prargs:
+
+ printf '"%b"\n' "$0" "$@" | nl -v0 -s": "
+
+### repeating a character (for example to print a line)
+
+A small trick: Combining printf and parameter expansion to draw a line
+
+ length=40
+ printf -v line '%*s' "$length"
+ echo ${line// /-}
+
+or:
+
+ length=40
+ eval printf -v line '%.0s-' {1..$length}
+
+### Replacement for some calls to date(1)
+
+The `%(...)T` format string is a direct interface to `strftime(3)`.
+
+ $ printf 'This is week %(%U/%Y)T.\n' -1
+ This is week 52/2010.
+
+Please read the manpage of `strftime(3)` to get more information about
+the supported formats.
+
+## differences from awk printf
+
+Awk also derives its *printf()* function from C, and therefore has
+similar format specifiers. However, in all versions of awk the space
+character is used as a string concatenation operator, so it cannot be
+used as an argument separator. **Arguments to awk printf must be
+separated by commas.** Some versions of awk do not require printf
+arguments to be surrounded by parentheses, but you should use them
+anyway to provide portability.
+
+In the following example, the two strings are concatenated by the
+intervening space so that no argument remains to fill the format.
+
+
+ $ echo "Foo" | awk '{ printf "%s\n" $1 }'
+ awk: (FILENAME=- FNR=1) fatal: not enough arguments to satisfy format string
+ `%s
+ Foo'
+ ^ ran out for this one
+
+Simply replacing the space with a comma and adding parentheses yields
+correct awk syntax.
+
+ $ echo "Foo" | awk '{ printf( "%s\n", $1 ) }'
+ Foo
+
+With appropriate metacharacter escaping the bash printf can be called
+from inside awk (as from perl and other languages that support shell
+callout) as long as you don\'t care about program efficiency or
+readability.
+
+ echo "Foo" | awk '{ system( "printf \"%s\\n \" \"" $1 "\"" ) }'
+ Foo
+
+## Differences from C, and portability considerations
+
+- The a, A, e, E, f, F, g, and G conversions are supported by Bash,
+ but not required by POSIX.
+
+```{=html}
+
+```
+- There is no wide-character support (wprintf). For instance, if you
+ use `%c`, you\'re actually asking for the first byte of the
+ argument. Likewise, the maximum field width modifier (dot) in
+ combination with `%s` goes by bytes, not characters. This limits
+ some of printf\'s functionality to working with ascii only. ksh93\'s
+ `printf` supports the `L` modifier with `%s` and `%c` (but so far
+ not `%S` or `%C`) in order to treat precision as character width,
+ not byte count. zsh appears to adjust itself dynamically based upon
+ `LANG` and `LC_CTYPE`. If `LC_CTYPE=C`, zsh will throw \"character
+ not in range\" errors, and otherwise supports wide characters
+ automatically if a variable-width encoding is set for the current
+ locale.
+
+```{=html}
+
+```
+- Bash recognizes and skips over any characters present in the length
+ modifiers specified by POSIX during format string parsing.
+
+``` c|builtins/printf.def
+#define LENMODS "hjlLtz"
+...
+/* skip possible format modifiers */
+modstart = fmt;
+while (*fmt && strchr (LENMODS, *fmt))
+fmt++;
+```
+
+- mksh has no built-in printf by default (usually). There is an
+ unsupported compile-time option to include a very poor, basically
+ unusable implementation. For the most part you must rely upon the
+ system\'s `/usr/bin/printf` or equivalent. The mksh maintainer
+ recommends using `print`. The development version (post- R40f) adds
+ a new parameter expansion in the form of `${name@Q}` which fills the
+ role of `printf %q` \-- expanding in a shell-escaped format.
+
+```{=html}
+
+```
+- ksh93 optimizes builtins run from within a command substitution and
+ which have no redirections to run in the shell\'s process. Therefore
+ the `printf -v` functionality can be closely matched by
+ `var=$(printf ...)` without a big performance hit.
+
+```{=html}
+
+```
+ # Illustrates Bash-like behavior. Redefining printf is usually unnecessary / not recommended.
+ function printf {
+ case $1 in
+ -v)
+ shift
+ nameref x=$1
+ shift
+ x=$(command printf "$@")
+ ;;
+ *)
+ command printf "$@"
+ esac
+ }
+ builtin cut
+ print $$
+ printf -v 'foo[2]' '%d\n' "$(cut -d ' ' -f 1 /proc/self/stat)"
+ typeset -p foo
+ # 22461
+ # typeset -a foo=([2]=22461)
+
+- The optional Bash loadable `print` may be useful for ksh
+ compatibility and to overcome some of
+ [echo](commands/builtin/echo)\'s portability pitfalls. Bash, ksh93,
+ and zsh\'s `print` have an `-f` option which takes a `printf` format
+ string and applies it to the remaining arguments. Bash lists the
+ synopsis as:
+ `print: print [-Rnprs] [-u unit] [-f format] [arguments]`. However,
+ only `-Rrnfu` are actually functional. Internally, `-p` is a noop
+ (it doesn\'t tie in with Bash coprocs at all), and `-s` only sets a
+ flag but has no effect. `-Cev` are unimplemented.
+
+```{=html}
+
+```
+- Assigning to variables: The `printf -v` way is slightly different to
+ the way using command-substitution. [Command
+ substitution](/syntax/expansion/cmdsubst) removes trailing newlines
+ before substituting the text, `printf -v` preserves all output.
+
+## See also
+
+- SUS: [printf
+ utility](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html)
+ and [printf()
+ function](http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html)
+- [Code snip: Print a horizontal
+ line](/snipplets/print_horizontal_line) uses some `printf` examples
+- [Greg\'s BashFAQ 18: How can I use numbers with leading zeros in a
+ loop, e.g., 01, 02?](BashFAQ>018)
diff --git a/docs/commands/builtin/read.md b/docs/commands/builtin/read.md
new file mode 100644
index 0000000..fe3f406
--- /dev/null
+++ b/docs/commands/builtin/read.md
@@ -0,0 +1,269 @@
+# The read builtin command
+
+*read something about read here!*
+
+## Synopsis
+
+ read [-ers] [-u ] [-t ] [-p ] [-a ] [-n ] [-N ] [-d ] [-i ] []
+
+## Description
+
+The `read` builtin reads **one line** of data (text, user input, \...)
+from standard input or a supplied filedescriptor number into one or more
+variables named by ``.
+
+Since Bash 4.3-alpha, `read` skips any `NUL` (ASCII code 0) characters
+in input.
+
+If `` is given, the line is word-split using
+[IFS](/syntax/shellvars#IFS) variable, and every word is assigned to one
+``. The remaining words are all assigned to the last `` if
+more words than variable names are present.
+
+\ If no `` is given, the whole line
+read (without performing word-splitting!) is assigned to the shell
+variable [REPLY](/syntax/shellvars#REPLY). Then, `REPLY` really contains
+the line as it was read, without stripping pre- and postfix spaces and
+other things!
+
+ while read -r; do
+ printf '"%s"\n' "$REPLY"
+ done <<<" a line with prefix and postfix space "
+
+\
+
+If a timeout is given, or if the shell variable
+[TMOUT](/syntax/shellvars#TMOUT) is set, it is counted from initially
+waiting for input until the completion of input (i.e. until the complete
+line is read). That means the timeout can occur during input, too.
+
+### Options
+
+ Option Description
+ ---------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ `-a ` read the data word-wise into the specified array `` instead of normal variables
+ `-d ` recognize `` as data-end, rather than ``
+ `-e` on interactive shells: use Bash\'s readline interface to read the data. Since version 5.1-alpha, this can also be used on specified file descriptors using `-u`
+ `-i ` preloads the input buffer with text from ``, only works when Readline (`-e`) is used
+ `-n ` reads `` characters of input, then quits
+ `-N ` reads `` characters of input, *ignoring any delimiter*, then quits
+ `-p ` the prompt string `` is output (without a trailing automatic newline) before the read is performed
+ `-r` raw input - **disables** interpretion of **backslash escapes** and **line-continuation** in the read data
+ `-s` secure input - don\'t echo input if on a terminal (passwords!)
+ `-t ` wait for data `` seconds, then quit (exit code 1). Fractional seconds (\"5.33\") are allowed since Bash 4. A value of 0 immediately returns and indicates if data is waiting in the exit code. Timeout is indicated by an exit code greater than 128. If timeout arrives before data is read completely (before end-of-line), the partial data is saved.
+ `-u ` use the filedescriptor number `` rather than `stdin` (0)
+
+When both, `-a ` and a variable name `` is given, then the
+array is set, but not the variable.
+
+Of course it\'s valid to set individual array elements without using
+`-a`:
+
+ read MYARRAY[5]
+
+\
+
+Reading into array elements using the syntax above **may cause [pathname
+expansion](/syntax/expansion/globs) to occur**.
+
+Example: You are in a directory with a file named `x1`, and you want to
+read into an array `x`, index `1` with
+
+ read x[1]
+
+then pathname expansion will expand to the filename `x1` and break your
+processing!
+
+Even worse, if `nullglob` is set, your array/index will disappear.
+
+To avoid this, either **disable pathname expansion** or **quote** the
+array name and index:
+
+ read 'x[1]'
+
+\
+
+### Return status
+
+ Status Reason
+ -------- ---------------------------------------------------
+ 0 no error
+ 0 error when assigning to a read-only variable [^1]
+ 2 invalid option
+ \>128 timeout (see `-t`)
+ !=0 invalid filedescriptor supplied to `-u`
+ !=0 end-of-file reached
+
+### read without -r
+
+Essentially all you need to know about `-r` is to **ALWAYS** use it. The
+exact behavior you get without `-r` is completely useless even for weird
+purposes. It basically allows the escaping of input which matches
+something in IFS, and also escapes line continuations. It\'s explained
+pretty well in the [POSIX
+read](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/read.html#tag_20_109)
+spec.
+
+ 2012-05-23 13:48:31 geirha it should only remove the backslashes, not change \n and \t and such into newlines and tabs
+ 2012-05-23 13:49:00 ormaaj so that's what read without -r does?
+ 2012-05-23 13:49:16 geirha no, -r doesn't remove the backslashes
+ 2012-05-23 13:49:34 ormaaj I thought read <<<'str' was equivalent to read -r <<<$'str'
+ 2012-05-23 13:49:38 geirha # read x y <<< 'foo\ bar baz'; echo "<$x><$y>"
+ 2012-05-23 13:49:40 shbot geirha:
+ 2012-05-23 13:50:32 geirha no, read without -r is mostly pointless. Damn bourne
+ 2012-05-23 13:51:08 ormaaj So it's mostly (entirely) used to escape spaces
+ 2012-05-23 13:51:24 ormaaj and insert newlines
+ 2012-05-23 13:51:47 geirha ormaaj: you mostly get the same effect as using \ at the prompt
+ 2012-05-23 13:52:04 geirha echo \" outputs a " , read x <<< '\"' reads a "
+ 2012-05-23 13:52:32 ormaaj oh weird
+ 2012-05-23 13:52:46 * ormaaj struggles to think of a point to that...
+ 2012-05-23 13:53:01 geirha ormaaj: ask Bourne :P
+ 2012-05-23 13:53:20 geirha (not Jason)
+ 2012-05-23 13:53:56 ormaaj hm thanks anyway :)
+
+## Examples
+
+### Rudimentary cat replacement
+
+A rudimentary replacement for the `cat` command: read lines of input
+from a file and print them on the terminal.
+
+ opossum() {
+ while read -r; do
+ printf "%s\n" "$REPLY"
+ done <"$1"
+ }
+
+[**Note:**]{.underline} Here, `read -r` and the default `REPLY` is used,
+because we want to have the real literal line, without any mangeling.
+`printf` is used, because (depending on settings), `echo` may interpret
+some baskslash-escapes or switches (like `-n`).
+
+### Press any key\...
+
+Remember the MSDOS `pause` command? Here\'s something similar:
+
+ pause() {
+ local dummy
+ read -s -r -p "Press any key to continue..." -n 1 dummy
+ }
+
+Notes:
+
+- `-s` to suppress terminal echo (printing)
+- `-r` to not interpret special characters (like waiting for a second
+ character if somebody presses the backslash)
+
+### Reading Columns
+
+#### Simple Split
+
+Read can be used to split a string:
+
+ var="one two three"
+ read -r col1 col2 col3 <<< "$var"
+ printf "col1: %s col2: %s col3 %s\n" "$col1" "$col2" "$col3"
+
+Take care that you cannot use a pipe:
+
+ echo "$var" | read col1 col2 col3 # does not work!
+ printf "col1: %s col2: %s col3 %s\n" "$col1" "$col2" "$col3"
+
+Why? because the commands of the pipe run in subshells that cannot
+modify the parent shell. As a result, the variables `col1`, `col2` and
+`col3` of the parent shell are not modified (see article:
+[processtree](/scripting/processtree)).
+
+If the variable has more fields than there are variables, the last
+variable get the remaining of the line:
+
+ read col1 col2 col3 <<< "one two three four"
+ printf "%s\n" "$col3" #prints three four
+
+#### Changing The Separator
+
+By default reads separates the line in fields using spaces or tabs. You
+can modify this using the *special variable*
+[IFS](/syntax/shellvars#IFS), the Internal Field Separator.
+
+ IFS=":" read -r col1 col2 <<< "hello:world"
+ printf "col1: %s col2: %s\n" "$col1" "$col2"
+
+Here we use the `var=value command` syntax to set the environment of
+`read` temporarily. We could have set `IFS` normally, but then we would
+have to take care to save its value and restore it afterward
+(`OLD=$IFS IFS=":"; read ....;IFS=$OLD`).
+
+The default `IFS` is special in that 2 fields can be separated by one or
+more space or tab. When you set `IFS` to something besides whitespace
+(space or tab), the fields are separated by **exactly** one character:
+
+ IFS=":" read -r col1 col2 col3 <<< "hello::world"
+ printf "col1: %s col2: %s col3 %s\n" "$col1" "$col2" "$col3"
+
+See how the `::` in the middle infact defines an additional *empty
+field*.
+
+The fields are separated by exactly one character, but the character can
+be different between each field:
+
+ IFS=":|@" read -r col1 col2 col3 col4 <<< "hello:world|in@bash"
+ printf "col1: %s col2: %s col3 %s col4 %s\n" "$col1" "$col2" "$col3" "$col4"
+
+### Are you sure?
+
+ asksure() {
+ echo -n "Are you sure (Y/N)? "
+ while read -r -n 1 -s answer; do
+ if [[ $answer = [YyNn] ]]; then
+ [[ $answer = [Yy] ]] && retval=0
+ [[ $answer = [Nn] ]] && retval=1
+ break
+ fi
+ done
+
+ echo # just a final linefeed, optics...
+
+ return $retval
+ }
+
+ ### using it
+ if asksure; then
+ echo "Okay, performing rm -rf / then, master...."
+ else
+ echo "Pfff..."
+ fi
+
+### Ask for a path with a default value
+
+[**Note:**]{.underline} The `-i` option was introduced with Bash 4
+
+ read -e -p "Enter the path to the file: " -i "/usr/local/etc/" FILEPATH
+
+The user will be prompted, he can just accept the default, or edit it.
+
+### Multichar-IFS: Parsing a simple date/time string
+
+Here, `IFS` contains both, a colon and a space. The fields of the
+date/time string are recognized correctly.
+
+ datetime="2008:07:04 00:34:45"
+ IFS=": " read -r year month day hour minute second <<< "$datetime"
+
+## Portability considerations
+
+- POSIX(r) only specified the `-r` option (raw read); `-r` is not only
+ POSIX, you can find it in earlier Bourne source code
+- POSIX(r) doesn\'t support arrays
+- `REPLY` is not POSIX(r), you need to set `IFS` to the empty string
+ to get the whole line for shells that don\'t know `REPLY`.
+ `while IFS= read -r line; do
+ ...
+ done < text.txt
+ `
+
+## See also
+
+- Internal: [The printf builtin command](/commands/builtin/printf)
+
+[^1]: fixed in 4.2-rc1
diff --git a/docs/commands/builtin/readonly.md b/docs/commands/builtin/readonly.md
new file mode 100644
index 0000000..140512f
--- /dev/null
+++ b/docs/commands/builtin/readonly.md
@@ -0,0 +1,45 @@
+# The readonly builtin command
+
+## Synopsis
+
+ readonly [-p] [-a] [-A] [-f] [NAME[=VALUE] ...]
+
+## Description
+
+The `readonly` builtin command is used to mark variables or functions as
+read-only, which means unchangeable. This implies that it can\'t be
+unset anymore. A `readonly` variable may not be redefined in child
+scopes. A readonly global may not be redefined as a function local
+variable. Simple command environment assignments may not reference
+readonly variables.
+
+### Options
+
+ Option Description
+ -------- ------------------------------------------------------------------------------------------------------------------------
+ `-a` refer to normal arrays
+ `-A` refer to associative arrays
+ `-f` refer to functions
+ `-p` print all read-only variables or functions, `-a`, `-A` and `-f` can be used to filter. The output is reusable as input
+
+An argument of `--` disables further option processing.
+
+### Return status
+
+ Status Reason
+ -------- --------------------------------
+ 0 no error
+ !=0 invalid option
+ !=0 invalid combination of options
+ !=0 a given `NAME` is invalid
+
+## Examples
+
+## Portability considerations
+
+- in POSIX(r), only the `-p` option is specified
+
+## See also
+
+- [declare](/commands/builtin/declare)
+- [unset](/commands/builtin/unset)
diff --git a/docs/commands/builtin/return.md b/docs/commands/builtin/return.md
new file mode 100644
index 0000000..f4adca4
--- /dev/null
+++ b/docs/commands/builtin/return.md
@@ -0,0 +1,35 @@
+# The return builtin command
+
+## Synopsis
+
+ return [N]
+
+## Description
+
+The `return` command returns from a shell function.
+
+If `N` is given, the return code to the caller is set to `N`. If not,
+the returned status the the status of the most recently executed command
+(i.e. `$?`).
+
+### Options
+
+There are no options.
+
+### Exit status
+
+If everything is okay, the `return` command doesn\'t come back. If it
+comes back, there was a problem in doing the return.
+
+ Status Reason
+ -------- -------------------------------------------------------------------------
+ 1 `return` was called while not being in a shell function or sourced file
+
+## Examples
+
+## Portability considerations
+
+## See also
+
+- [The exit builtin command](/commands/builtin/exit)
+- [The exit status](/dict/terms/exit_status)
diff --git a/docs/commands/builtin/set.md b/docs/commands/builtin/set.md
new file mode 100644
index 0000000..7aff0d0
--- /dev/null
+++ b/docs/commands/builtin/set.md
@@ -0,0 +1,81 @@
+# The set builtin command
+
+FIXME incomplete - text, examples, maybe extended description
+
+## Synopsis
+
+ set [--abefhkmnptuvxBCHP] <-o OPTIONNAME> [-][--]
+
+## Description
+
+`set` is primarily made to
+
+- set the positional parameters (see [handling positional
+ parameters](/scripting/posparams)) to ``
+- set shell attributes with short options (see below)
+- set shell attributes with long option names (see below)
+
+Without any options, `set` displays all shell- and environment-variables
+(only is POSIX-mode) in a re-usable format `NAME=VALUE`.
+
+### Attributes
+
+All attributes below can be switched on using `-X` and switched off
+using `+X`. This is done because of the historical meaning of the `-` to
+set flags (true for most commands on UNIX(r)).
+
+ Flag Optionname Description
+ ------ ---------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ `-a` `allexport` Automatically mark new and altered variables to be exported to subsequent environments.
+ `-b` `notify` Don\'t wait for the next prompt to print when showing the reports for a terminated background job (only with job control)
+ `-e` `errexit` When set, the shell exits when a simple command in a command list exits non-zero (`FALSE`). This is not done in situations, where the exit code is already checked (`if`, `while`, `until`, `||`, `&&`)
+ `-f` `noglob` Disable [pathname expansion](/syntax/expansion/globs) (globbing)
+ `-h` `hashall` Remembers the location of commands when they\'re called (hashing). Enabled by default.
+ `-k` `keyword` Allows to place environment-assignments everywhere in the commandline, not only infront of the called command.
+ `-m` `monitor` **Monitor mode**. With job control, a short descriptive line is printed when a backgroud job ends. Default is \"on\" for interactive shells (with job control).
+ `-n` `noexec` Read and parse but **do not execute commands** - useful for checking scripts for syntax errors. Ignored by interactive shells.
+ `-o` Set/unset attributes with long option names, e.g. `set -o noglob`. The long option names are in the second column of this table. If no option name is given, all options are printed with their current status.
+ `-p` `privileged` Turn on privileged mode.
+ `-t` `onecmd` Exit after reading and executing **one** command.
+ `-u` `nounset` Treat unset variables as an error when performing parameter expansion. Non-interactive shells exit on this error.
+ `-v` `verbose` Print shell input lines as they are read - useful for debugging.
+ `-x` `xtrace` Print commands just before execution - with all expansions and substitutions done, and words marked - useful for debugging.
+ `-B` `braceexpand` The shell performs [brace expansion](/syntax/expansion/brace) This is on by default.
+ `-C` \`noclobber` Don\'t overwrite files on redirection operations. You can override that by specifying the `>|` redirection operator when needed. See [redirection](/syntax/redirection)
+ `-E` `errtrace` `ERR`-traps are inherited by by shell functions, command substitutions, and commands executed in a subshell environment.
+ `-H` `histexpand` Enable `!`-style history expansion. Defaults to `on` for interactive shells.
+ `-P` `physical` Don\'t follow symlinks when changing directories - use the physical filesystem structure.
+ `-T` `functrace` `DEBUG`- and `RETURN`-traps are inherited by subsequent environments, like `-E` for `ERR` trap.
+ `-` \"End of options\" - all following arguments are assigned to the positional parameters, even when they begin with a dash. `-x` and `-v` options are turned off. Positional parameters are unchanged (unlike using `--`!) when no further arguments are given.
+ `--` If no arguments follow, the positional parameters are unset. With arguments, the positional parameters are set, even if the strings begin with a `-` (dash) like an option.
+ Long options usable with `-o` without a short equivalent
+ `emacs` Use an emacs-style command line editing interface. This is enabled by default when the shell is interactive, unless the shell is started with `--noediting` option.
+ `history` If set, command historization is done (enabled by default on interactive shells)
+ `ignoreeof` The effect is as if the shell command `IGNOREEOF=10` had been executed. See [shell variables](/syntax/shellvars).
+ `nolog` **(currently ignored)**
+ `pipefail` If set, the exit code from a pipeline is different from the normal (\"last command in pipeline\") behaviour: `TRUE` when no command failed, `FALSE` when something failed (code of the rightmost command that failed)
+ `posix` When set, Bash runs in POSIX mode.
+ `vi` Enables a `vi`-style command line editing interface.
+
+## Examples
+
+Tag a part of a shell script to output debugging information (`-x`):
+
+``` bash
+#!/bin/bash
+...
+set -x # on
+...
+set +x # off
+...
+```
+
+## Portability considerations
+
+`set` and its basic behaviour and options are specified by POSIX(r).
+However, options that influence Bash-specific things are not portable,
+naturally.
+
+## See also
+
+- Internal: [The shopt builtin command](/commands/builtin/shopt)
diff --git a/docs/commands/builtin/shift.md b/docs/commands/builtin/shift.md
new file mode 100644
index 0000000..7a1b1f3
--- /dev/null
+++ b/docs/commands/builtin/shift.md
@@ -0,0 +1,88 @@
+# The shift builtin command
+
+## Synopsis
+
+ shift [n]
+
+## Description
+
+The `shift` builtin command is used to \"shift\" the positional
+parameters by the given number `n` or by 1, if no number is given.
+
+This means, the number and the position of the positional parameters are
+changed. The very first positional parameter is discarded, the second
+becomes the first one, etc.
+
+Imagine the following set of positional parameters (`$1` to `$4`):
+
+ 1 This
+ --- ------
+ 2 is
+ 3 a
+ 4 test
+
+When you use `shift 1`, they will be changed to:
+
+ 1 is
+ --- ------
+ 2 a
+ 3 test
+
+The [special parameter](/syntax/shellvars#special_parameters) `$#` will
+reflect the final number of positional parameters.
+
+If the number given is 0, no changes are made to the positional
+parameters.
+
+### Options
+
+There are no options.
+
+### Return status
+
+ Status Reason
+ -------- -----------------------------------------------------------------------------------------------------
+ 0 no error
+ 1 non-numeric argument
+ 1 given number (or the default 1) is bigger than the number of actually present positional parameters
+ 1 given number is negative
+
+## Examples
+
+## Portability considerations
+
+- The `shift` builtin command is specified by POSIX(r).
+- Many shells will throw a fatal error when attempting to `shift` more
+ than the number of positional parameters. **POSIX does not require
+ that behavior**. Bash (even in POSIX mode) and Zsh return 1 when
+ there are no args, and no error output is produced unless the
+ [shift_verbose](internals/shell_options#shift_verbose)
+ [shopt](commands/builtin/shopt) option is enabled. Ksh93, pdksh,
+ posh, mksh, and dash, all throw useless fatal shell
+ errors.`$ dash -c 'f() { if shift; then echo "$1"; else echo "no args"; fi; }; f'
+ dash: 1: shift: can't shift that many
+ ` In most shells, you can work around this problem using the
+ [command](/commands/builtin/command) builtin to suppress fatal
+ errors caused by *special builtins*. \ \$ dash -c \'f() { if
+ command shift 2\>/dev/null; then echo \"\$1\"; else echo \"no
+ args\"; fi; }; f\'
+
+no args \
While, POSIX requires this behavior, it isn\'t very
+obvious and some shells don\'t do it correctly. To work around this, you
+can use something like:
+
+\ \$ mksh -c \'f() { if ! \${1+false} && shift; then echo
+\"\$1\"; else echo \"no args\"; fi; }; f\' no args \
~~The mksh
+maintainer refuses to change either the `shift` or `command` builtins.~~
+[Fixed](https://github.com/MirBSD/mksh/commit/996e05548ab82f7ef2dea61f109cc7b6d13837fa).
+(Thanks!)
+
+- Perhaps almost as bad as the above, busybox sh\'s `shift` always
+ returns success, even when attempting to shift beyond the final
+ argument. \ \$ bb -c \'f() { if shift; then echo \"\$1\";
+ else echo \"no args\"; fi; }; f\'
+
+(no output) \
The above mksh workaround will work in this case
+too.
+
+## See also
diff --git a/docs/commands/builtin/shopt.md b/docs/commands/builtin/shopt.md
new file mode 100644
index 0000000..96ed762
--- /dev/null
+++ b/docs/commands/builtin/shopt.md
@@ -0,0 +1,51 @@
+# The shopt builtin command
+
+The `shopt` builtin manages [shell options](/internals/shell_options), a
+set of boolean (`on`/`off`) configuration variables that control the
+behaviour of the shell.
+
+## Synopsis
+
+ shopt [-pqsu] [-o]
+
+## Description
+
+Note: Some of these options and other shell options can also be set with
+[the set builtin](/commands/builtin/set).
+
+### Options
+
+ Option Description
+ -------- -----------------------------------------------------------------------------------------------------------------------------
+ `-o` Restrict the values of `` to only those also known by [the set builtin](/commands/builtin/set)
+ `-p` Print all shell options and their current value. **Default**.
+ `-q` Quiet mode. Set exit code if named option is set. For multiple options: `TRUE` if all options are set, `FALSE` otherwise
+ `-s` Enable ([s]{.underline}et) the shell options named by `` or list all *enabled* options if no names are given
+ `-u` Disabe ([u]{.underline}nset) the shell options named by `` or list all *disabled* options if no names are given
+
+As noted above, if only `-s` or `-u` are given without any option names,
+only the currently enabled (`-s`) or disabled (`-u`) options are
+printed.
+
+### Exit code
+
+When listing options, the exit code is `TRUE` (0), if all options are
+enabled, `FALSE` otherwise.
+
+When setting/unsetting an option, the exit code is `TRUE` unless the
+named option doesn\'t exitst.
+
+## Examples
+
+Enable the `nullglob` option:
+
+ shopt -s nullglob
+
+## Portability considerations
+
+The `shopt` command is not portable accross different shells.
+
+## See also
+
+- Internal: [The set builtin command](/commands/builtin/set)
+- Internal: [List of shell options](/internals/shell_options)
diff --git a/docs/commands/builtin/trap.md b/docs/commands/builtin/trap.md
new file mode 100644
index 0000000..ebfd925
--- /dev/null
+++ b/docs/commands/builtin/trap.md
@@ -0,0 +1,72 @@
+# The trap builtin command
+
+## Synopsis
+
+ trap [-lp] [[ARGUMENT] SIGNAL]
+
+## Description
+
+The `trap` command is used to \"trap\" signals and other events. In this
+context, \"trapping\" means to install handler code.
+
+The shell code `ARGUMENT` is to be read and executed whenever the shell
+receives a signal or another event `SIGNAL`. The given `SIGNAL`
+specification can be
+
+- the name of a signal with the SIG prefix, e.g. `SIGTERM`
+- the name of a signal without the SIG prefix, e.g. `TERM`
+- the number of a signal (see `trap -l`), e.g. `15`
+- the name or number of a special event (see table below), e.g. `EXIT`
+
+Without any options or operands, `trap` prints a list of installed traps
+in a reusable format (equivalent to the `-p` option).
+
+Special `ARGUMENT`s
+
+- if `ARGUMENT` is absent or `-` (dash), the signal/event handler is
+ reset to its original value
+- if `ARGUMENT` is the null string, the signal/event is ignored
+
+Special events
+
+ Name Code Description
+ ---------- ------ --------------------------------------------------------------------------------------------------------------------------------------------
+ `EXIT` 0 executed on shell exit
+ `DEBUG` executed before every simple command
+ `RETURN` executed when a shell function or a sourced code finishes executing
+ `ERR` executed each time a command\'s failure would cause the shell to exit when the [`-e` option (`errexit`)](/commands/builtin/set) is enabled
+
+### Options
+
+ Option Description
+ -------- ------------------------------------------------------------------------------------------
+ `-l` print a list of signal names and their corresponding numbers
+ `-p` display the trap commands associated with each signal specification in a reusable format
+
+### Return status
+
+ Status Reason
+ -------- ------------------------------
+ 0 no error/success
+ !=0 invalid option
+ !=0 invalid signal specification
+
+## Examples
+
+### List installed traps
+
+ trap
+
+### Ignore terminal interrupt (Ctrl-C, SIGINT)
+
+ trap '' INT
+
+## Portability considerations
+
+- `trap` is specified by POSIX(R) without the `-l` and `-p` options
+- in POSIX(R), beside signals, only `EXIT` (0) is valid as an event
+
+## See also
+
+- [the set command](/commands/builtin/set) for the `-e` (`errexit`)
+ option
diff --git a/docs/commands/builtin/unset.md b/docs/commands/builtin/unset.md
new file mode 100644
index 0000000..cda7424
--- /dev/null
+++ b/docs/commands/builtin/unset.md
@@ -0,0 +1,181 @@
+# The unset builtin command
+
+## Synopsis
+
+ unset [-f|v] [-n] [NAME ...]
+
+## Description
+
+The `unset` builtin command is used to unset values and attributes of
+shell variables and functions. Without any option, `unset` tries to
+unset a variable first, then a function.
+
+### Options
+
+ Option Description
+ -------- --------------------------------------------------------------------------------------------------------------
+ `-f` treats each `NAME` as a function name
+ `-v` treats each `NAME` as a variable name
+ `-n` treats each `NAME` as a name reference and unsets the variable itself rather than the variable it references
+
+### Exit status
+
+ Status Reason
+ -------- ----------------------------------------------------
+ 0 no error
+ !=0 invalid option
+ !=0 invalid combination of options (`-v` **and** `-f`)
+ !=0 a given `NAME` is read-only
+
+## Examples
+
+ unset -v EDITOR
+
+ unset -f myfunc1 myfunc2
+
+### Scope
+
+In bash, unset has some interesting properties due to its unique dynamic
+scope. If a local variable is both declared and unset (by calling unset
+on the local) from within the same function scope, then the variable
+appears unset to that scope and all child scopes until either returning
+from the function, or another local variable of the same name is
+declared underneath where the original variable was unset. In other
+words, the variable looks unset to everything until returning from the
+function in which the variable was set (and unset), at which point
+variables of the same name from higher scopes are uncovered and
+accessible once again.
+
+If however unset is called from a child scope relative to where a local
+variable has been set, then the variable of the same name in the
+next-outermost scope becomes visible to its scope and all children - as
+if the variable that was unset was never set to begin with. This
+property allows looking upwards through the stack as variable names are
+unset, so long as unset and the local it unsets aren\'t together in the
+same scope level.
+
+Here\'s a demonstration of this behavior.
+
+ #!/usr/bin/env bash
+
+ FUNCNEST=10
+
+ # Direct recursion depth.
+ # Search up the stack for the first non-FUNCNAME[1] and count how deep we are.
+ callDepth() {
+ # Strip "main" off the end of FUNCNAME[@] if current function is named "main" and
+ # Bash added an extra "main" for non-interactive scripts.
+ if [[ main == !(!("${FUNCNAME[1]}")|!("${FUNCNAME[-1]}")) && $- != *i* ]]; then
+ local -a 'fnames=("${FUNCNAME[@]:1:${#FUNCNAME[@]}-2}")'
+ else
+ local -a 'fnames=("${FUNCNAME[@]:1}")'
+ fi
+
+ if (( ! ${#fnames[@]} )); then
+ printf 0
+ return
+ fi
+
+ local n
+ while [[ $fnames == ${fnames[++n]} ]]; do
+ :
+ done
+
+ printf -- $n
+ }
+
+ # This function is the magic stack walker.
+ unset2() {
+ unset -v -- "$@"
+ }
+
+ f() {
+ local a
+ if (( (a=$(callDepth)) <= 4 )); then
+ (( a == 1 )) && unset a
+ (( a == 2 )) && declare -g a='global scope yo'
+ f
+ else
+ trap 'declare -p a' DEBUG
+ unset2 a # declare -- a="5"
+ unset a a # declare -- a="4"
+ unset a # declare -- a="2"
+ unset a # ./unset-tests: line 44: declare: a: not found
+ : # declare -- a="global scope yo"
+ fi
+ }
+
+ a='global scope'
+ f
+
+ # vim: set fenc=utf-8 ff=unix ts=4 sts=4 sw=4 ft=sh nowrap et:
+
+output:
+
+ declare -- a="5"
+ declare -- a="4"
+ declare -- a="2"
+ ./unset-tests: line 44: declare: a: not found
+ declare -- a="global scope yo"
+
+Some things to observe:
+
+- `unset2` is only really needed once. We remain 5 levels deep in
+ `f`\'s for the remaining `unset` calls, which peel away the outer
+ layers of `a`\'s.
+- Notice that the \"a\" is unset using an ordinary unset command at
+ recursion depth 1, and subsequently calling unset reveals a again in
+ the global scope, which has since been modified in a lower scope
+ using declare -g.
+- Declaring a global with declare -g bypasses all locals and sets or
+ modifies the variable of the global scope (outside of all
+ functions). It has no affect on the visibility of the global.
+- This doesn\'t apply to individual array elements. If two local
+ arrays of the same name appear in different scopes, the entire array
+ of the inner scope needs to be unset before any elements of the
+ outer array become visible. This makes \"unset\" and \"unset2\"
+ identical for individual array elements, and for arrays as a whole,
+ unset and unset2 behave as they do for scalar variables.
+
+### Args
+
+Like several other Bash builtins that take parameter names, unset
+expands its arguments.
+
+ ~ $ ( a=({a..d}); unset 'a[2]'; declare -p a )
+ declare -a a='([0]="a" [1]="b" [3]="d")'
+
+As usual in such cases, it\'s important to quote the args to avoid
+accidental results such as globbing.
+
+ ~ $ ( a=({a..d}) b=a c=d d=1; set -x; unset "${b}["{2..3}-c\]; declare -p a )
+ + unset 'a[2-1]' 'a[3-1]'
+ + declare -p a
+ declare -a a='([0]="a" [3]="d")'
+
+Of course hard to follow indirection is still possible whenever
+arithmetic is involved, also as shown above, even without extra
+expansions.
+
+In Bash, the `unset` builtin only evaluates array subscripts if the
+array itself is set.
+
+ ~ $ ( unset -v 'a[$(echo a was set >&2)0]' )
+ ~ $ ( a=(); unset -v 'a[$(echo a was set >&2)0]' )
+ a was set
+
+## Portability considerations
+
+Quoting POSIX:
+
+ If neither -f nor -v is specified, name refers to a variable; if a variable by that name does not exist, it is unspecified whether a function by that name, if any, shall be unset.
+
+Therefore, it is recommended to explicitly specify `-f` or `-v` when
+using `unset`. Also, I prefer it as a matter of style.
+
+## See also
+
+- [declare](/commands/builtin/declare)
+- [unset](/commands/builtin/unset)
+- [POSIX `unset`
+ utility](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_29)
diff --git a/docs/commands/builtin/wait.md b/docs/commands/builtin/wait.md
new file mode 100644
index 0000000..78139b8
--- /dev/null
+++ b/docs/commands/builtin/wait.md
@@ -0,0 +1,44 @@
+# The wait builtin command
+
+## Synopsis
+
+ wait [-f] [-n] [-p VARNAME] [ID...]
+
+## Description
+
+The `wait` builtin command is used to wait for job completion and return
+exit status.
+
+- if `ID` is a job specification, it waits for all processes in the
+ pipeline of this job
+- waits for a specific job (asynchronous command) and report its exit
+ status if one or more `ID` is given
+- waits for all running jobs (asynchronous commands)
+- waits for \"the next\" job (`-n` option)
+- waits for termination instead of status change (`-f` option)
+
+`ID` may be an operating system process identifier or a shell job
+specification.
+
+### Options
+
+ Option Description
+ -------------- ---------------------------------------------------------------------------------------------------------------------------------
+ `-n` Waits for \"the next\" child to exit (as opposed to \"all children\" without this option). Accepts a list of IDs (jobs)
+ `-f` Waits for the termination of the given `ID` (instead of waiting for a status change only)
+ `-p VARNAME` When waiting for a list (-n) or all jobs, writes the job ID to the job that was actually terminated into the variable `VARNAME`
+
+### Return status
+
+The return status is the return status of the job waited for, or
+
+ Status Reason
+ -------- -------------------------------------------------
+ 0 waited for all jobs in shell\'s job list
+ 1 the given `ID` is not a valid job or process ID
+
+## Examples
+
+## Portability considerations
+
+## See also