Updated table formatting, call-outs, html comments, improper escapes.

This commit is contained in:
Sahal Ansari 2024-10-07 23:00:17 -05:00
parent de70cb886e
commit cd90135cce
70 changed files with 2304 additions and 2424 deletions

View File

@ -8,7 +8,7 @@
The `caller` builtin command is used to print execution frames of
subroutine calls. Without giving a framenumber, the topmost execution
frame information is printed (\"who called me\") wile linenumber and
frame information is printed ("who called me") wile linenumber and
filename.
When an execution frame number is given (0 - topmost), the linenumber,
@ -22,10 +22,10 @@ used in a loop (see the examples section below).
The code below defines a function `die` that is used to exit the
program. It prints a list of execution frames, starting with the topmost
frame (0). The topmost frame is the \"caller of the die function\", in
this case function \"f1\".
frame (0). The topmost frame is the "caller of the die function", in
this case function "f1".
This way, you can print a \"stack trace\" for debugging or logging
This way, you can print a "stack trace" for debugging or logging
purposes.
The code is made very simple, just to show the basic purposes.
@ -70,9 +70,9 @@ f3
[Bashdb](http://bashdb.sourceforge.net/) can assist in using some of
Bash's more advanced debug features.
- The Bash manpage and help text specifies that the argument to
`caller` is an \"expr\" (whatever that means). Only an integer is
`caller` is an "expr" (whatever that means). Only an integer is
actually allowed, with no special interpretation of an
\"expression\" as far as we can tell.
"expression" as far as we can tell.
## Portability considerations

View File

@ -37,7 +37,7 @@ Below, `[-+]X` indicates an attribute, use `-X` to set the attribute,
`[-+]A` make NAMEs associative arrays
`[-+]c` **Undocumented** convert NAMEs to \"capcase\" on assignment (makes the first letter upper-case and the rest lower). Requires Bash built with `-DCASEMOD_CAPCASE`
`[-+]c` **Undocumented** convert NAMEs to "capcase" on assignment (makes the first letter upper-case and the rest lower). Requires Bash built with `-DCASEMOD_CAPCASE`
`-f` restrict action or display to function names and definitions (removing with `+f` is valid syntax, but leads to an error message)
@ -45,20 +45,20 @@ Below, `[-+]X` indicates an attribute, use `-X` to set the attribute,
`-g` create global variables when used in a shell function; otherwise ignored (by default, `declare` declares local scope variables when used in shell functions)
`[-+]i` make NAMEs have the \"integer\" attribute
`[-+]i` make NAMEs have the "integer" attribute
`[-+]l` convert NAMEs to lower case on assignment (makes sure the variable contains only lower case letters)
`[-+]n` make NAME a reference to the variable named by its value. Introduced in Bash 4.3-alpha.\
\'\' \${!NAME}\'\' reveals the reference variable name, VALUE.\
Use `unset -n NAME` to unset the variable. (`unset -v NAME` unsets the VALUE variable.)\
`[-+]n` make NAME a reference to the variable named by its value. Introduced in Bash 4.3-alpha.
''`${!NAME}`'' reveals the reference variable name, VALUE.
Use `unset -n NAME` to unset the variable. (`unset -v NAME` unsets the VALUE variable.)
Use `[[ -R NAME ]]` to test if NAME has been set to a VALUE, another variable's name.
`-p` display the attributes and value of each NAME
`[-+]r` make NAMEs readonly (removing with `+r` is valid syntax, but not possible)
`[-+]t` make NAMEs have the \"trace\" attribute (effective only for functions)
`[-+]t` make NAMEs have the "trace" attribute (effective only for functions)
`[-+]u` convert NAMEs to upper case on assignment (makes sure the variable contains only upper case letters)
@ -76,13 +76,13 @@ Below, `[-+]X` indicates an attribute, use `-X` to set the attribute,
!= 0 assignment to a readonly variable
!= 0 removing the readonly-attribute from a readonly variable
!= 0 assignment to an array variable without the compound assignment syntax (`array=(...)`)
!= 0 attempt to use `+a` to \"destroy\" an array
!= 0 attempt to use `+a` to "destroy" an array
!= 0 attemt to display a non-existent function with `-f`
## Notes
Unix shells offer very few datatypes. Bash and some other shells extend
this by allowing \"attributes\" to be set on variable names. The only
this by allowing "attributes" to be set on variable names. The only
attributes specified by POSIX are `export` and `readonly`, which are set
by their own dedicated builtins. Datatypes in bash have a few other
interesting capabilities such as the ability to modify data on
@ -92,7 +92,7 @@ assignment.
### Display defined functions
`declare -f` can be used to display all defined functions\...
`declare -f` can be used to display all defined functions...
$ declare -f
foo ()
@ -104,7 +104,7 @@ assignment.
echo "Hello World!"
}
\...or just a specific defined function.
...or just a specific defined function.
$ declare -f foo
foo ()
@ -172,7 +172,7 @@ for details. ksh93 namerefs are much more powerful than Bash's.
considers `typeset` a special builtin, while Bash does not - even in
POSIX mode. If you use `typeset`, you should attempt to only use it
in portable ways.
- **todo** nameref portability\...
- **todo** nameref portability...
## See also

View File

@ -56,17 +56,14 @@ if given.
case `-n` is always treated as a string, and backslash escapes are
interpreted by default. `dash` has the misfeature of following this
and interpreting escapes by default, but includes a `-n` feature for
suppressing newlines nevertheless.\
\
In practice, if you\'re able to assume a korn-like shell including
suppressing newlines nevertheless.
In practice, if you're able to assume a korn-like shell including
bash, mksh, or zsh, `echo` when used in simple cases is generally
reliable. For example, in the very common situation in which echo is
supplied with a single argument and whose output is to have a
newline appended, using `echo` is considered common practice.
```{=html}
<!-- -->
```
- **Never use options to `echo`! *Ever*!** Any time you feel tempted
to use `echo -e`, `-n`, or any other special feature of echo, **use
[printf](../../commands/builtin/printf.md) instead!** If portability is a
@ -76,9 +73,6 @@ if given.
\$\'\...\' \'\'if targeting only shells that support this special
quoting style.
```{=html}
<!-- -->
```
- `ksh93` has a `print` command, which if coding specifically for
`ksh93` should be preferred over `echo`.
[printf](../../commands/builtin/printf.md) still includes most of the

View File

@ -55,7 +55,7 @@ This code defines a set of identical functions using the supplied names.
### Using printf %q
The `printf %q` format string performs shell escaping on its arguments.
This makes `printf %q` the \"anti-eval\" - with each pass of a string
This makes `printf %q` the "anti-eval" - with each pass of a string
through printf requiring another `eval` to peel off the escaping again.
while (( ++n <= 5 )) || ! evalBall="eval $evalBall"; do
@ -112,16 +112,11 @@ controlled carefully by the caller is a good way to use it.
`setopt POSIX_BUILTINS` -- looks like a regression). This works
correctly in Bash POSIX mode, Dash, and mksh.
```{=html}
<!-- -->
```
- `eval` is another one of the few Bash builtins with keyword-like
conditional parsing of arguments that are in the form of compound
assignments.
```{=html}
<!-- -->
```
$ ( eval a=( a b\\ c d ); printf '<%s> ' "${a[@]}"; echo ) # Only works in Bash.
<a> <b c> <d>
$ ( x=a; eval "$x"=( a b\\ c d ); printf '<%s> ' "${a[@]}"; echo ) # Argument is no longer in the form of a valid assignment, therefore ordinary parsing rules apply.
@ -168,7 +163,7 @@ identical to those of [let](../../commands/builtin/let.md).
eval](http://mywiki.wooledge.org/BashFAQ/006#Assigning_indirect.2BAC8-reference_variables)
- [More indirection via
eval](http://fvue.nl/wiki/Bash:_Passing_variables_by_reference)
- [Martin Väth's \"push\"](https://github.com/vaeth/push) --
- [Martin Väth's "push"](https://github.com/vaeth/push) --
`printf %q` work-alike for POSIX.
- [The \"magic alias\"
- [The "magic alias"
hack](http://www.chiark.greenend.org.uk/~sgtatham/aliases.html)

View File

@ -27,7 +27,7 @@ The `kill` command is a Bash builtin command instead of relying on the
external `kill` command of the operating system to
- be able to use shell job specifications instead of Unix process IDs
- be able to send signals (\"kill something\") also, when your process
- be able to send signals ("kill something") also, when your process
limit is reached
### Options

View File

@ -10,8 +10,8 @@ The `let` builtin command evaluates each supplied word from left to
right as an [arithmetic expression](../../syntax/arith_expr.md) and returns an
exit code according to the truth value of the rightmost expression.
- 0 (TRUE) when `arg` evaluated to not 0 (arithmetic \"true\")
- 1 (FALSE) when `arg` evaluated to 0 (arithmetic \"false\")
- 0 (TRUE) when `arg` evaluated to not 0 (arithmetic "true")
- 1 (FALSE) when `arg` evaluated to 0 (arithmetic "false")
For this return code mapping, please see [this
section](../../syntax/arith_expr.md#arithmetic_expressions_and_return_codes).
@ -50,7 +50,7 @@ used above only to illustrate how this precedence works. </WRAP>
Unlike `((`, being a simple command `let` has its own environment. In
Bash, built-ins that can set variables process any arithmetic under
their own environment, which makes the variable effectively \"local\" to
their own environment, which makes the variable effectively "local" to
the builtin unless the variable is also set or modified by the builtin.
This differs in other shells, such as ksh93, where environment
assignments to regular builtins are always local even if the variable is
@ -84,7 +84,7 @@ needed.
choose `let` over `((` expecting it to work in more places.
- [expr(1)](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/expr.html#tag_20_42)
is a command one is likely to come across sooner or later. While it
is more \"standard\" than `let`, the above should always be
is more "standard" than `let`, the above should always be
preferred. Both [arithmetic expansion](../../syntax/arith_expr.md)s and the
`[` test operator are specified by POSIX(r) and satisfy almost all
of expr's use-cases. Unlike `let`, `expr` cannot assign directly to
@ -108,4 +108,4 @@ needed.
- Internal: [arithmetic evaluation compound
command](../../syntax/ccmd/arithmetic_eval.md)
[^1]: \...
[^1]: ...

View File

@ -30,17 +30,11 @@ way, and takes all the same options, with 3 exceptions:
have a builtin called `local`, but some such as `dash` and the
busybox shell do.
```{=html}
<!-- -->
```
- The behavior of function scope is not defined by POSIX, however
local variables are implemented widely by bourne-like shells, and
behavior differs substantially. Even the`dash` shell has local
variables.
```{=html}
<!-- -->
```
- In ksh93, using POSIX-style function definitions, `typeset` doesn't
set `local` variables, but rather acts upon variables of the
next-outermost scope (e.g. setting attributes). Using `typeset`
@ -48,8 +42,8 @@ way, and takes all the same options, with 3 exceptions:
variables follow roughly
[lexical-scoping](http://community.schemewiki.org/?lexical-scope),
except that functions themselves don't have scope, just like Bash.
This means that even functions defined within a \"function's
scope\" don't have access to non-local variables except through
This means that even functions defined within a "function's
scope" don't have access to non-local variables except through
`namerefs`.
## See also

View File

@ -14,7 +14,7 @@ This builtin is also accessible using the command name `readarray`.
handling standard input (the other being `read`). `mapfile` reads lines
of standard input and assigns each to the elements of an indexed array.
If no array name is given, the default array name is `MAPFILE`. The
target array must be a \"normal\" integer indexed array.
target array must be a "normal" integer indexed array.
`mapfile` returns success (0) unless an invalid option is given or the
given array `ARRAY` is set readonly.
@ -47,9 +47,9 @@ Here's a real-world example of interactive use borrowed from Gentoo
workflow. Xorg updates require rebuilding drivers, and the
Gentoo-suggested command is less than ideal, so let's Bashify it. The
first command produces a list of packages, one per line. We can read
those into the array named \"args\" using `mapfile`, stripping trailing
newlines with the \'-t\' option. The resulting array is then expanded
into the arguments of the \"emerge\" command - an interface to Gentoo's
those into the array named "args" using `mapfile`, stripping trailing
newlines with the '`-t`' option. The resulting array is then expanded
into the arguments of the `emerge` command - an interface to Gentoo's
package manager. This type of usage can make for a safe and effective
replacement for xargs(1) in certain situations. Unlike xargs, all
arguments are guaranteed to be passed to a single invocation of the
@ -59,7 +59,7 @@ business.
# eix --only-names -IC x11-drivers | { mapfile -t args; emerge -av1 "${args[@]}" <&1; }
Note the use of command grouping to keep the emerge command inside the
pipe's subshell and within the scope of \"args\". Also note the unusual
pipe's subshell and within the scope of "args". Also note the unusual
redirection. This is because the -a flag makes emerge interactive,
asking the user for confirmation before continuing, and checking with
isatty(3) to abort if stdin isn't pointed at a terminal. Since stdin of
@ -71,11 +71,11 @@ wiki: <http://mywiki.wooledge.org/BashFAQ/024>
### The callback
This is one of the more unusual features of a Bash builtin. As far as
I\'m able to tell, the exact behavior is as follows: If defined, as each
I'm able to tell, the exact behavior is as follows: If defined, as each
line is read, the code contained within the string argument to the -C
flag is evaluated and executed *before* the assignment of each array
element. There are no restrictions to this string, which can be any
arbitrary code, however, two additional \"words\" are automatically
arbitrary code, however, two additional "words" are automatically
appended to the end before evaluation: the index, and corresponding line
of data to be assigned to the next array element. Since all this happens
before assignment, the callback feature cannot be used to modify the
@ -91,9 +91,9 @@ the appended words from printf.
Really, the intended usage is for the callback to just contain the name
of a function, with the extra words passed to it as arguments. If
you\'re going to use callbacks at all, this is probably the best way
because it allows for easy access to the arguments with no ugly \"code
in a string\".
you're going to use callbacks at all, this is probably the best way
because it allows for easy access to the arguments with no ugly "code
in a string".
$ foo() { echo "|$1|"; }; mapfile -n 11 -c 2 -C 'foo' <file
|2|
@ -121,13 +121,13 @@ illustrates the callback behavior:
Since redirects are syntactically allowed anywhere in a command, we put
it before the printf to stay out of the way of additional arguments.
Rather than opening \"outfile<n>\" for appending on each call by
Rather than opening "outfile&lt;n&gt;" for appending on each call by
calculating the filename, open an FD for each first and calculate which
FD to send output to by measuring the size of x mod 2. The zero-width
format specification is used to absorb the index number argument.
Another variation might be to add each of these lines to the elements of
separate arrays. I\'ll leave dissecting this one as an exercise for the
separate arrays. I'll leave dissecting this one as an exercise for the
reader. This is quite the hack but illustrates some interesting
properties of printf -v and mapfile -C (which you should probably never
use in real code).
@ -147,7 +147,7 @@ use in real code).
This example based on yet another #bash question illustrates mapfile in
combination with read. The sample input is the heredoc to `main`. The
goal is to build a \"struct\" based upon records in the input file made
goal is to build a "struct" based upon records in the input file made
up of the numbers following the colon on each line. Every 3rd line is a
key followed by 2 corresponding fields. The showRecord function takes a
key and returns the record.

View File

@ -1,19 +1,22 @@
# The printf command
<div center round todo box 70%> 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! </div> <div
center round tip 70%> [**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).
!!! warning "FIXME"
This is a very big topic that needs experience - please fill in
missing information, extend the descriptions, and correct the details
if you can!
[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?&.md#using_printf_inside_of_awk). </div>
!!! info "Bash-Builtin"
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](#differences-from-awk-printf).
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
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.
@ -28,7 +31,7 @@ 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
exclusive, they collide. A "new" command had to be invented to solve
the issue.
## Syntax
@ -50,27 +53,28 @@ 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)
---------- -------------------------------------------------------------------------------------------------------------------------------
| Option | Description |
|--------|-------------|
|`-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.
<note warning> 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.
!!! danger "Danger"
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")'
$ 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.md), and a similar one to
[mapfile](../../commands/builtin/mapfile.md), though performing expansions into
their arguments is less common. </note>
...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.md), and a similar one to
[mapfile](../../commands/builtin/mapfile.md), though performing expansions into
their arguments is less common.
### Arguments
@ -78,16 +82,16 @@ 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**
| 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,
<u>**If more arguments than format specifiers**</u> 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
@ -97,15 +101,15 @@ Take care to avoid [word splitting](../../syntax/expansion/wordsplit.md), as
accidentally passing the wrong number of arguments can produce wildly
different and unexpected results. See [this article](../../syntax/words.md).
<note warning> [**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`!):
!!! danger "Attention"
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
printf '%d\n' 08
</note>
### Format strings
@ -115,7 +119,7 @@ family. Only format specifiers that end in one of the letters
To print a literal `%` (percent-sign), use `%%` in the format string.
[**Again:**]{.underline} Every format specifier expects an associated
<u>**Again:**</u> Every format specifier expects an associated
argument provided!
These specifiers have different names, depending who you ask. But they
@ -124,30 +128,30 @@ 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 `<N>±e<N>` 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)
| 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 `<N>±e<N>` 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:
@ -162,26 +166,26 @@ introductory `%` and the character that specifies the format:
#### Field and printing modifiers
Field output format
--------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
`<N>` **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
`<space>` 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
|Field | output format|
|-------|-------------|
|`<N>`|**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|
|`<space>`|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}
<u>**The "alternative format" modifier `#`:**</u>
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
|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
@ -204,30 +208,30 @@ number of digits to print (zero-padding!).
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 `?`
`<NNN>` Interprets `<NNN>` as **octal** number and prints the corresponding character from the character set
`\0<NNN>` same as `<NNN>`
`\x<NNN>` Interprets `<NNN>` as **hexadecimal** number and prints the corresponding character from the character set (**3 digits**)
`\u<NNNN>` same as `\x<NNN>`, but **4 digits**
`\U<NNNNNNNN>` same as `\x<NNN>`, but **8 digits**
|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 `?`|
|`<NNN>`|Interprets `<NNN>` as **octal** number and prints the corresponding character from the character set|
|`\0<NNN>`|same as `<NNN>`|
|`\x<NNN>`|Interprets `<NNN>` as **hexadecimal** number and prints the corresponding character from the character set (**3 digits**)|
|`\u<NNNN>`|same as `\x<NNN>`, but **4 digits**|
|`\U<NNNNNNNN>`|same as `\x<NNN>`, 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.
------ -------------------------------------------------------------------------------------------------------------------------------------------------------------
|Escape Rule|Description|
|-----------|-----------|
|`\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.
@ -267,18 +271,17 @@ This small loop prints all numbers from 0 to 127 in
- octal
- hex
```{=html}
<!-- -->
```bash
for ((x=0; x <= 127; x++)); do
printf '%3d | %04o | 0x%02x\n' "$x" "$x" "$x"
done
```
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, \...):
digits, ...):
the_mac="0:13:ce:7:7a:ad"
@ -375,29 +378,23 @@ readability.
- 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
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
`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
``` c title="builtins/printf.def"
#define LENMODS "hjlLtz"
...
/* skip possible format modifiers */
@ -405,7 +402,6 @@ 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
@ -414,36 +410,32 @@ fmt++;
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}
<!-- -->
```bash
# 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)
```
# 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
@ -455,10 +447,6 @@ fmt++;
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.md) removes trailing newlines

View File

@ -8,7 +8,7 @@
## Description
The `read` builtin reads **one line** of data (text, user input, \...)
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 `<NAME...>`.
@ -50,7 +50,7 @@ line is read). That means the timeout can occur during input, too.
`-p <PROMPT>` the prompt string `<PROMPT>` 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 <TIMEOUT>` wait for data `<TIMEOUT>` 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.
`-t <TIMEOUT>` wait for data `<TIMEOUT>` 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 <FD>` use the filedescriptor number `<FD>` rather than `stdin` (0)
When both, `-a <ARRAY>` and a variable name `<NAME>` is given, then the
@ -134,12 +134,12 @@ from a file and print them on the terminal.
done <"$1"
}
[**Note:**]{.underline} Here, `read -r` and the default `REPLY` is used,
<u>**Note:**</u> 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\...
### Press any key...
Remember the MSDOS `pause` command? Here's something similar:
@ -236,7 +236,7 @@ be different between each field:
### Ask for a path with a default value
[**Note:**]{.underline} The `-i` option was introduced with Bash 4
<u>**Note:**</u> The `-i` option was introduced with Bash 4
read -e -p "Enter the path to the file: " -i "/usr/local/etc/" FILEPATH

View File

@ -15,23 +15,23 @@ 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
|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
|Status|Reason|
|-|-|
|0|no error|
|!=0|invalid option|
|!=0|invalid combination of options|
|!=0|a given `NAME` is invalid|
## Examples

View File

@ -21,9 +21,9 @@ There are no options.
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
|Status|Reason|
|-|-|
|1|`return` was called while not being in a shell function or sourced file|
## Examples

View File

@ -1,6 +1,7 @@
# The set builtin command
FIXME incomplete - text, examples, maybe extended description
!!! warning "FIXME"
incomplete text, examples, maybe extended description
## Synopsis
@ -24,38 +25,38 @@ 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.md) (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.md) This is on by default.
`-C` <BOOKMARK:tag_noclobber>`noclobber` Don't overwrite files on redirection operations. You can override that by specifying the `>|` redirection operator when needed. See [redirection](../../syntax/redirection.md)
`-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.md).
`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.
|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.md) (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.md) 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.md)|
|`-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.md).|
||`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

View File

@ -6,7 +6,7 @@
## Description
The `shift` builtin command is used to \"shift\" the positional
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
@ -15,18 +15,20 @@ becomes the first one, etc.
Imagine the following set of positional parameters (`$1` to `$4`):
1 This
--- ------
2 is
3 a
4 test
|Positional Parameter|Value|
|-|-|
|1|This
|2|is|
|3|a|
|4|test|
When you use `shift 1`, they will be changed to:
1 is
--- ------
2 a
3 test
|Positional Parameter|Value|
|-|-|
|1|is|
|2|a|
|3|test|
The [special parameter](../../syntax/shellvars.md#special_parameters) `$#` will
reflect the final number of positional parameters.
@ -40,12 +42,12 @@ 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
|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
@ -59,30 +61,37 @@ There are no options.
[shift_verbose](../../internals/shell_options.md#shift_verbose)
[shopt](../../commands/builtin/shopt.md) 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'
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
```
In most shells, you can work around this problem using the
`command` builtin to suppress fatal
errors caused by *special builtins*. <code> \$ dash -c \'f() { if
command shift 2>/dev/null; then echo \"\$1\"; else echo \"no
args\"; fi; }; f\'
no args </code> While, POSIX requires this behavior, it isn't very
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:
<code> \$ mksh -c \'f() { if ! \${1+false} && shift; then echo
\"\$1\"; else echo \"no args\"; fi; }; f\' no args </code> ~~The mksh
maintainer refuses to change either the `shift` or `command` builtins.~~
```
$ mksh -c 'f() { if ! ${1+false} && shift; then echo "$1"; else echo "no args"; fi; }; f'
no args
```
<del>The mksh maintainer refuses to change either the `shift` or `command` builtins.</del>
[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. <code> \$ bb -c \'f() { if shift; then echo \"\$1\";
else echo \"no args\"; fi; }; f\'
(no output) </code> The above mksh workaround will work in this case
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

View File

@ -15,13 +15,13 @@ Note: Some of these options and other shell options can also be set with
### Options
Option Description
-------- -----------------------------------------------------------------------------------------------------------------------------
`-o` Restrict the values of `<OPTNAME...>` to only those also known by [the set builtin](../../commands/builtin/set.md)
`-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 `<OPTNAME...>` or list all *enabled* options if no names are given
`-u` Disabe ([u]{.underline}nset) the shell options named by `<OPTNAME...>` or list all *disabled* options if no names are given
|Option|Description|
|------|-----------|
|`-o`|Restrict the values of `<OPTNAME...>` to only those also known by [the set builtin](../../commands/builtin/set.md)|
|`-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 (<u>s</u>et) the shell options named by `<OPTNAME...>` or list all *enabled* options if no names are given|
|`-u`|Disabe (<u>u</u>nset) the shell options named by `<OPTNAME...>` 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

View File

@ -6,8 +6,8 @@
## Description
The `trap` command is used to \"trap\" signals and other events. In this
context, \"trapping\" means to install handler code.
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`
@ -29,27 +29,27 @@ Special `ARGUMENT`s
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.md) is enabled
|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.md) 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
|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
|Status|Reason|
|------|------|
|0|no error/success|
|!=0|invalid option|
|!=0|invalid signal specification|
## Examples

View File

@ -12,20 +12,20 @@ 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
|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
|Status|Reason|
|------|------|
|0|no error|
|!=0|invalid option|
|!=0|invalid combination of options (`-v` **and** `-f`)|
|!=0|a given `NAME` is read-only|
## Examples
@ -123,7 +123,7 @@ 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
- 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.
@ -133,7 +133,7 @@ Some things to observe:
- 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\"
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.

View File

@ -14,7 +14,7 @@ exit status.
- 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 "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
@ -22,20 +22,20 @@ 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`
|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
|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

View File

@ -1,7 +1,7 @@
# Parameter
Also the article for: [variable]{.underline}, [positional
parameter]{.underline}, [special parameter]{.underline}
Also the article for: <u>variable</u>, <u>positional
parameter</u>, <u>special parameter</u>
In Bash, a parameter is simply an entity that stores values and can be
referenced. Depending on the type, the parameters can be set directly,

View File

@ -10,7 +10,8 @@ This behaviour alone doesn't help much. A shell knits some intelligence
and flow control around the possibility to execute commands - it's a
complete commandline-oriented user-interface (UI).
FIXME
!!! warning "FIXME"
tbd.
## See also

View File

@ -12,9 +12,9 @@ tags:
## Introduction
dc(1) is a non standard, but commonly found, reverse-polish Desk
Calculator. According to Ken Thompson, \"dc is the oldest language on
Calculator. According to Ken Thompson, "dc is the oldest language on
Unix; it was written on the PDP-7 and ported to the PDP-11 before Unix
\[itself\] was ported\".
\[itself\] was ported".
Historically the standard bc(1) has been implemented as a *front-end to
dc*.
@ -26,15 +26,15 @@ stack first, then an operation is applied to them. Instead of writing
`1+1`, you write `1 1+`.
By default `dc`, unlike `bc`, doesn't print anything, the result is
pushed on the stack. You have to use the \"p\" command to print the
pushed on the stack. You have to use the "p" command to print the
element at the top of the stack. Thus a simple operation looks like:
$ dc <<< '1 1+pq'
2
I used a \"here string\" present in bash 3.x, ksh93 and zsh. if your
I used a "here string" present in bash 3.x, ksh93 and zsh. if your
shell doesn't support this, you can use `echo '1 1+p' | dc` or if you
have GNU `dc`, you can use `dc -e '1 1 +p`\'.
have GNU `dc`, you can use `dc -e '1 1 +p'`.
Of course, you can also just run `dc` and enter the commands.
@ -70,7 +70,7 @@ The **output** is converted to **base 10** by default
## Scale And Base
`dc` is a calulator with abitrary precision, by default this precision
is 0. thus `dc <<< "5 4/p"` prints \"1\".
is 0. thus `dc <<< "5 4/p"` prints "1".
We can increase the precision using the `k` command. It pops the value
at the top of the stack and uses it as the precision argument:
@ -123,9 +123,6 @@ There are two basic commands to manipulate the stack:
- `d` duplicates the top of the stack
- `c` clears the stack
```{=html}
<!-- -->
```
$ dc << EOF
2 # put 2 on the stack
d # duplicate i.e. put another 2 on the stack
@ -228,7 +225,7 @@ we are used to reading:
EOF
Some `dc` have `>R <R =R`, GNU `dc` had some more, check your manual.
Note that the test \"consumes\" its operands: the 2 first elements are
Note that the test "consumes" its operands: the 2 first elements are
popped off the stack (you can verify that
`dc <<< "[f]sR 2 1 >R 1 2 >R f"` doesn't print anything)
@ -263,13 +260,13 @@ remove all those extra spaces newlines and comments:
dc <<< '[lip1-si0li>L]sL10silLx'
dc <<< '[p1-d0<L]sL10lLx' # use the stack instead of a register
I\'ll let you figure out the second example, it's not hard, it uses the
I'll let you figure out the second example, it's not hard, it uses the
stack instead of a register for the index.
## Next
Check your dc manual, i haven't decribed everything, like arrays (only
documented with \"; : are used by bc(1) for array operations\" on
documented with "; : are used by bc(1) for array operations" on
solaris, probably because *echo \'1 0:a 0Sa 2 0:a La 0;ap\' \| dc*
results in //Segmentation Fault (core dump) //, the latest solaris uses
GNU dc)

View File

@ -10,7 +10,7 @@ tags:
# Collapsing Functions
## What is a \"Collapsing Function\"?
## What is a "Collapsing Function"?
A collapsing function is a function whose behavior changes depending
upon the circumstances under which it's run. Function collapsing is
@ -21,7 +21,7 @@ never changes.
Function collapsing requires some static feature in the environment. A
common example is a script that gives the user the option of having
\"verbose\" output.
"verbose" output.
#!/bin/bash
@ -49,58 +49,63 @@ common example is a script that gives the user the option of having
## How does it work?
The first time you run chatter(), the function redefines itself based on
the value of verbose. Thereafter, chatter doesn't check \$verbose, it
the value of verbose. Thereafter, chatter doesn't check `$verbose`, it
simply is. Further calls to the function reflect its collapsed nature.
If verbose is unset, chatter will echo nothing, with no extra effort
from the developer.
## More examples
FIXME Add more examples!
!!! warning "FIXME"
Add more examples!
# Somewhat more portable find -executable
# FIXME/UNTESTED (I don't have access to all of the different versions of find.)
# Usage: find PATH ARGS -- use find like normal, except use -executable instead of
# various versions of -perm /+ blah blah and hacks
```bash
# Somewhat more portable find -executable
# FIXME/UNTESTED (I don't have access to all of the different versions of find.)
# Usage: find PATH ARGS -- use find like normal, except use -executable instead of
# various versions of -perm /+ blah blah and hacks
find() {
hash find || { echo 'find not found!'; exit 1; }
# We can be pretty sure "$0" should be executable.
if [[ $(command find "$0" -executable 2> /dev/null) ]]; then
unset -f find # We can just use the command find
elif [[ $(command find "$0" -perm /u+x 2> /dev/null) ]]; then
find() {
hash find || { echo 'find not found!'; exit 1; }
# We can be pretty sure "$0" should be executable.
if [[ $(command find "$0" -executable 2> /dev/null) ]]; then
unset -f find # We can just use the command find
elif [[ $(command find "$0" -perm /u+x 2> /dev/null) ]]; then
find() {
typeset arg args
for arg do
[[ $arg = -executable ]] && args+=(-perm /u+x) || args+=("$arg")
done
command find "${args[@]}"
}
elif [[ $(command find "$0" -perm +u+x 2> /dev/null) ]]; then
find() {
typeset arg args
for arg do
[[ $arg = -executable ]] && args+=(-perm +u+x) || args+=("$arg")
done
command find "${args[@]}"
}
else # Last resort
find() {
typeset arg args
for arg do
[[ $arg = -executable ]] && args+=(-exec test -x {} \; -print) || args+=("$arg")
done
command find "${args[@]}"
}
fi
find "$@"
typeset arg args
for arg do
[[ $arg = -executable ]] && args+=(-perm /u+x) || args+=("$arg")
done
command find "${args[@]}"
}
elif [[ $(command find "$0" -perm +u+x 2> /dev/null) ]]; then
find() {
typeset arg args
for arg do
[[ $arg = -executable ]] && args+=(-perm +u+x) || args+=("$arg")
done
command find "${args[@]}"
}
else # Last resort
find() {
typeset arg args
for arg do
[[ $arg = -executable ]] && args+=(-exec test -x {} \; -print) || args+=("$arg")
done
command find "${args[@]}"
}
fi
find "$@"
}
```
#!/bin/bash
# Using collapsing functions to turn debug messages on/off
```bash
#!/bin/bash
# Using collapsing functions to turn debug messages on/off
[ "--debug" = "$1" ] && dbg=echo || dbg=:
[ "--debug" = "$1" ] && dbg=echo || dbg=:
# From now on if you use $dbg instead of echo, you can select if messages will be shown
# From now on if you use $dbg instead of echo, you can select if messages will be shown
$dbg "This message will only be displayed if --debug is specified at the command line
$dbg "This message will only be displayed if --debug is specified at the command line
```

View File

@ -16,7 +16,7 @@ tags:
For this task, you don't have to write large parser routines (unless
you want it 100% secure or you want a special file syntax) - you can use
the Bash source command. The file to be sourced should be formated in
key=\"value\" format, otherwise bash will try to interpret commands:
key="value" format, otherwise bash will try to interpret commands:
#!/bin/bash
echo "Reading config...." >&2
@ -50,7 +50,7 @@ usage of the dot is identical:
## Per-user configs
There's also a way to provide a system-wide config file in /etc and a
custom config in \~/(user's home) to override system-wide defaults. In
custom config in ~/(user's home) to override system-wide defaults. In
the following example, the if/then construct is used to check for the
existance of a user-specific config:
@ -66,11 +66,11 @@ existance of a user-specific config:
As mentioned earlier, the sourced file can contain anything a Bash
script can. Essentially, it **is** an included Bash script. That creates
security issues. A malicicios person can \"execute\" arbitrary code when
security issues. A malicicios person can "execute" arbitrary code when
your script is sourcing its config file. You might want to allow only
constructs in the form `NAME=VALUE` in that file (variable assignment
syntax) and maybe comments (though technically, comments are
unimportant). Imagine the following \"config file\", containing some
unimportant). Imagine the following "config file", containing some
malicious code:
# cool config file for my even cooler script
@ -107,7 +107,7 @@ filters by description:
# now source it, either the original or the filtered variant
source "$configfile"
**[To make clear what it does:]{.underline}** egrep checks if the file
<u>**To make clear what it does:**</u> egrep checks if the file
contains something we don't want, if yes, egrep filters the file and
writes the filtered contents to a new file. If done, the original file
name is changed to the name stored in the variable `configfile`. The

View File

@ -1,36 +1,36 @@
# Dissect a bad oneliner
``` bash
```bash
$ ls *.zip | while read i; do j=`echo $i | sed 's/.zip//g'`; mkdir $j; cd $j; unzip ../$i; cd ..; done
```
This is an actual one-liner someone asked about in `#bash`. **There are
several things wrong with it. Let's break it down!**
``` bash
```bash
$ ls *.zip | while read i; do ...; done
```
(Please read <http://mywiki.wooledge.org/ParsingLs>.) This command
executes `ls` on the expansion of `*.zip`. Assuming there are filenames
in the current directory that end in \'.zip\', ls will give a
in the current directory that end in '.zip', ls will give a
human-readable list of those names. The output of ls is not for parsing.
But in sh and bash alike, we can loop safely over the glob itself:
``` bash
```bash
$ for i in *.zip; do j=`echo $i | sed 's/.zip//g'`; mkdir $j; cd $j; unzip ../$i; cd ..; done
```
Let's break it down some more!
``` bash
```bash
j=`echo $i | sed 's/.zip//g'` # where $i is some name ending in '.zip'
```
The goal here seems to be get the filename without its `.zip` extension.
In fact, there is a POSIX(r)-compliant command to do this: `basename`
The implementation here is suboptimal in several ways, but the only
thing that's genuinely error-prone with this is \"`echo $i`\". Echoing
thing that's genuinely error-prone with this is "`echo $i`". Echoing
an *unquoted* variable means
[wordsplitting](../syntax/expansion/wordsplit.md) will take place, so any
whitespace in `$i` will essentially be normalized. In `sh` it is
@ -41,7 +41,7 @@ performance in a loop). Just for good measure, let's use the more
readable, [modern](../syntax/expansion/cmdsubst.md) `$()` construct instead
of the old style backticks:
``` bash
```bash
sh $ for i in *.zip; do j=$(basename "$i" ".zip"); mkdir $j; cd $j; unzip ../$i; cd ..; done
```
@ -49,27 +49,27 @@ In Bash we don't need the subshell or the external basename command.
See [Substring removal with parameter
expansion](../syntax/pe.md#substring_removal):
``` bash
```bash
bash $ for i in *.zip; do j="${i%.zip}"; mkdir $j; cd $j; unzip ../$i; cd ..; done
```
Let's keep going:
``` bash
```bash
$ mkdir $j; cd $j; ...; cd ..
```
As a programmer, you **never** know the situation under which your
program will run. Even if you do, the following best practice will never
hurt: When a following command depends on the success of a previous
command(s), check for success! You can do this with the \"`&&`\"
command(s), check for success! You can do this with the "`&&`"
conjunction, that way, if the previous command fails, bash will not try
to execute the following command(s). It's fully POSIX(r). Oh, and
remember what I said about [wordsplitting](../syntax/expansion/wordsplit.md)
in the previous step? Well, if you don't quote `$j`, wordsplitting can
happen again.
``` bash
```bash
$ mkdir "$j" && cd "$j" && ... && cd ..
```
@ -78,47 +78,47 @@ contains a slash? Then `cd ..` will not return to the original
directory. That's wrong! `cd -` causes cd to return to the previous
working directory, so it's a much better choice:
``` bash
```bash
$ mkdir "$j" && cd "$j" && ... && cd -
```
(If it occurred to you that I forgot to check for success after cd -,
good job! You could do this with `{ cd - || break; }`, but I\'m going to
good job! You could do this with `{ cd - || break; }`, but I'm going to
leave that out because it's verbose and I think it's likely that we
will be able to get back to our original working directory without a
problem.)
So now we have:
``` bash
```bash
sh $ for i in *.zip; do j=$(basename "$i" ".zip"); mkdir "$j" && cd "$j" && unzip ../$i && cd -; done
```
``` bash
```bash
bash $ for i in *.zip; do j="${i%.zip}"; mkdir "$j" && cd "$j" && unzip ../$i && cd -; done
```
Let's throw the `unzip` command back in the mix:
``` bash
```bash
mkdir "$j" && cd "$j" && unzip ../$i && cd -
```
Well, besides word splitting, there's nothing terribly wrong with this.
Still, did it occur to you that unzip might already be able to target a
directory? There isn't a standard for the `unzip` command, but all the
implementations I\'ve seen can do it with the -d flag. So we can drop
implementations I've seen can do it with the -d flag. So we can drop
the cd commands entirely:
``` bash
```bash
$ mkdir "$j" && unzip -d "$j" "$i"
```
``` bash
```bash
sh $ for i in *.zip; do j=$(basename "$i" ".zip"); mkdir "$j" && unzip -d "$j" "$i"; done
```
``` bash
```bash
bash $ for i in *.zip; do j="${i%.zip}"; mkdir "$j" && unzip -d "$j" "$i"; done
```

View File

@ -20,7 +20,7 @@ contents with `sed`, and the file is open elsewhere and read by some
process, you will find out that GNU `sed` and its `-i` option will not
allow you to edit the file. There are circumstances where you may need
that, e.g. editing active and open files, the lack of GNU, or other
`sed`, with \"in-place\" option available.
`sed`, with "in-place" option available.
Why `ed`?
@ -40,12 +40,12 @@ Since `ed` is an interactive text editor, it reads and executes commands
that come from `stdin`. There are several ways to feed our commands to
ed:
**[Pipelines]{.underline}**
**<u>Pipelines</u>**
echo '<ED-COMMANDS>' | ed <FILE>
To inject the needed newlines, etc. it may be easier to use the builtin
command, `printf` (\"help printf\"). Shown here as an example Bash
command, `printf` ("help printf"). Shown here as an example Bash
function to prefix text to file content:
@ -55,11 +55,11 @@ function to prefix text to file content:
printf '%s\n' H 1i "$1" . w | ed -s "$2"
}
**[Here-strings]{.underline}**
**<u>Here-strings</u>**
ed <FILE> <<< '<ED-COMMANDS>'
**[Here-documents]{.underline}**
**<u>Here-documents</u>**
ed <FILE> <<EOF
<ED-COMMANDS>
@ -71,17 +71,17 @@ it looks best here IMHO.
There are other ways to provide input to `ed`. For example, process
substitution. But these should be enough for daily needs.
Since `ed` wants commands separated by newlines, I\'ll use a special
Since `ed` wants commands separated by newlines, I'll use a special
Bash quoting method, the C-like strings `$'TEXT'`, as it can interpret a
set of various escape sequences and special characters. I\'ll use the
set of various escape sequences and special characters. I'll use the
`-s` option to make it less verbose.
## The basic interface
Check the `ed` manpage for details
Similar to `vi` or `vim`, `ed` has a \"command mode\" and an
\"interactive mode\". For non-interactive use, the command mode is the
Similar to `vi` or `vim`, `ed` has a "command mode" and an
"interactive mode". For non-interactive use, the command mode is the
usual choice.
Commands to `ed` have a simple and regular structure: zero, one, or two
@ -103,7 +103,7 @@ no RE can ever match a newline.
## Debugging your ed scripts
By default, `ed` is not very talkative and will simply print a \"?\"
By default, `ed` is not very talkative and will simply print a "?"
when an error occurs. Interactively you can use the `h` command to get a
short message explaining the last error. You can also turn on a mode
that makes `ed` automatically print this message with the `H` command.
@ -156,8 +156,8 @@ lines, it's considered an error.**
ed -s test.txt <<< $',s/Windows(R)-compatible/POSIX-conform/g\nw'
[Note:]{.underline} The comma as single address operator is an alias for
`1,$` (\"all lines\").
<u>Note:</u> The comma as single address operator is an alias for
`1,$` ("all lines").
#### Substitutions in specific lines
@ -188,7 +188,7 @@ regexp
#### Move a block of text
\...using the `m` command: `<ADDRESS> m <TARGET-ADDRESS>`
...using the `m` command: `<ADDRESS> m <TARGET-ADDRESS>`
This is definitely something that can't be done easily with sed.
@ -200,7 +200,7 @@ This is definitely something that can't be done easily with sed.
#### Copy a block of text
\...using the `t` command: `<ADDRESS> t <TARGET-ADDRESS>`
...using the `t` command: `<ADDRESS> t <TARGET-ADDRESS>`
You use the `t` command just like you use the `m` (move) command.
@ -212,7 +212,7 @@ You use the `t` command just like you use the `m` (move) command.
#### Join all lines
\...but leave the final newline intact. This is done by an extra
...but leave the final newline intact. This is done by an extra
command: `j` (join).
ed -s file <<< $'1,$j\nw'
@ -272,7 +272,7 @@ about it with the g (global) command:
**\_\_ an error stops the script \_\_**
You might think that it's not a problem and that the same thing happens
with sed and you\'re right, with the exception that if ed does not find
with sed and you're right, with the exception that if ed does not find
a pattern it's an error, while sed just continues with the next line.
For instance, let's say that you want to change foo to bar on the first
line of the file and add something after the next line, ed will stop if
@ -299,9 +299,9 @@ attempt the substitution on all non blank lines
**\_\_ shell parameters are expanded \_\_**
If you don't quote the delimiter, \$ has a special meaning. This sounds
If you don't quote the delimiter, `$` has a special meaning. This sounds
obvious but it's easy to forget this fact when you use addresses like
\$-1 or commands like \$a. Either quote the \$ or the delimiter:
`$-1` or commands like `$a`. Either quote the `$` or the delimiter:
#fails
ed -s file << EOF
@ -313,7 +313,7 @@ obvious but it's easy to forget this fact when you use addresses like
#ok
ed -s file << EOF
\$a
$a
last line
.
w
@ -327,9 +327,9 @@ obvious but it's easy to forget this fact when you use addresses like
w
EOF
**\_\_ \".\" is not a command \_\_**
**\_\_ "." is not a command \_\_**
The . used to terminate the command \"a\" must be the only thing on the
The . used to terminate the command "a" must be the only thing on the
line. take care if you indent the commands:
#ed doesn't care about the spaces before the commands, but the . must be the only thing on the line:
@ -358,7 +358,7 @@ expression => print). ref
### wc -l
Since the default for the `ed` \"print line number\" command is the last
Since the default for the `ed` "print line number" command is the last
line, a simple `=` (equal sign) will print this line number and thus the
number of lines of the file:
@ -366,23 +366,24 @@ number of lines of the file:
### cat
Yea, it's a joke\...
Yea, it's a joke...
ed -s file <<< $',p'
\...but a similar thing to `cat` showing line-endings and escapes can be
...but a similar thing to `cat` showing line-endings and escapes can be
done with the `list` command (l):
ed -s file <<< $',l'
FIXME to be continued
!!! warning "FIXME"
to be continued
## Links
Reference:
- [Gnu ed](http://www.gnu.org/software/ed/manual/ed_manual.html) - if
we had to guess, you\'re probably using this one.
we had to guess, you're probably using this one.
- POSIX
[ed](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ed.html#tag_20_38),
[ex](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ex.html#tag_20_40),

View File

@ -27,7 +27,7 @@ are:
- Being a builtin, `getopts` can set shell variables to use for
parsing (impossible for an *external* process!)
- There's no need to argue with several `getopt` implementations
which had buggy concepts in the past (whitespace, \...)
which had buggy concepts in the past (whitespace, ...)
- `getopts` is defined in POSIX(r).
------------------------------------------------------------------------
@ -38,7 +38,7 @@ parameters](../scripting/posparams.md).
### Terminology
It's useful to know what we\'re talking about here, so let's see\...
It's useful to know what we're talking about here, so let's see...
Consider the following command line:
mybackup -x -f /etc/mybackup.conf -r ./foo.txt ./bar.txt
@ -97,13 +97,13 @@ which means [end of options](../dict/end_of_options.md).
### Used variables
variable description
------------------------------------ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
[OPTIND](../syntax/shellvars.md#OPTIND) Holds the index to the next argument to be processed. This is how `getopts` \"remembers\" its own status between invocations. Also useful to shift the positional parameters after processing with `getopts`. `OPTIND` is initially set to 1, and **needs to be re-set to 1 if you want to parse anything again with getopts**
[OPTARG](../syntax/shellvars.md#OPTARG) This variable is set to any argument for an option found by `getopts`. It also contains the option flag of an unknown option.
[OPTERR](../syntax/shellvars.md#OPTERR) (Values 0 or 1) Indicates if Bash should display error messages generated by the `getopts` builtin. The value is initialized to **1** on every shell startup - so be sure to always set it to **0** if you don't want to see annoying messages! **`OPTERR` is not specified by POSIX for the `getopts` builtin utility --- only for the C `getopt()` function in `unistd.h` (`opterr`).** `OPTERR` is bash-specific and not supported by shells such as ksh93, mksh, zsh, or dash.
|variable|description|
|--------|-----------|
|[OPTIND](../syntax/shellvars.md#OPTIND)|Holds the index to the next argument to be processed. This is how `getopts` "remembers" its own status between invocations. Also useful to shift the positional parameters after processing with `getopts`. `OPTIND` is initially set to 1, and **needs to be re-set to 1 if you want to parse anything again with getopts**
|[OPTARG](../syntax/shellvars.md#OPTARG)|This variable is set to any argument for an option found by `getopts`. It also contains the option flag of an unknown option.|
|[OPTERR](../syntax/shellvars.md#OPTERR)|(Values 0 or 1) Indicates if Bash should display error messages generated by the `getopts` builtin. The value is initialized to **1** on every shell startup - so be sure to always set it to **0** if you don't want to see annoying messages! **`OPTERR` is not specified by POSIX for the `getopts` builtin utility --- only for the C `getopt()` function in `unistd.h` (`opterr`).** `OPTERR` is bash-specific and not supported by shells such as ksh93, mksh, zsh, or dash.|
`getopts` also uses these variables for error reporting (they\'re set to
`getopts` also uses these variables for error reporting (they're set to
value-combinations which arent possible in normal operation).
### Specify what you want
@ -114,10 +114,11 @@ The base-syntax for `getopts` is:
where:
`OPTSTRING` tells `getopts` which options to expect and where to expect arguments (see below)
------------- ------------------------------------------------------------------------------------
`VARNAME` tells `getopts` which shell-variable to use for option reporting
`ARGS` tells `getopts` to parse these optional words instead of the positional parameters
|Option|Description|
|------|-----------|
|`OPTSTRING`|tells `getopts` which options to expect and where to expect arguments (see below)|
|`VARNAME`|tells `getopts` which shell-variable to use for option reporting|
|`ARGS`|tells `getopts` to parse these optional words instead of the positional parameters|
#### The option-string
@ -136,7 +137,7 @@ an argument (i.e. to become `-A SOMETHING`) just do:
If the **very first character** of the option-string is a `:` (colon),
which would normally be nonsense because there's no option letter
preceding it, `getopts` switches to \"**silent error reporting mode**\".
preceding it, `getopts` switches to "**silent error reporting mode**".
In productive scripts, this is usually what you want because it allows
you to handle errors yourself without being disturbed by annoying
messages.
@ -177,15 +178,17 @@ are indicated in an easier way.
#### Verbose Mode
invalid option `VARNAME` is set to `?` (question-mark) and `OPTARG` is unset
----------------------------- ----------------------------------------------------------------------------------------------
required argument not found `VARNAME` is set to `?` (question-mark), `OPTARG` is unset and an *error message is printed*
|failure|message|
|-------|-------|
|invalid option|`VARNAME` is set to `?` (question-mark) and `OPTARG` is unset|
|required argument not found|`VARNAME` is set to `?` (question-mark), `OPTARG` is unset and an *error message is printed*|
#### Silent Mode
invalid option `VARNAME` is set to `?` (question-mark) and `OPTARG` is set to the (invalid) option character
----------------------------- -----------------------------------------------------------------------------------------------
required argument not found `VARNAME` is set to `:` (colon) and `OPTARG` contains the option-character in question
|failure|message|
|-------|-------|
|invalid option|`VARNAME` is set to `?` (question-mark) and `OPTARG` is set to the (invalid) option character|
|required argument not found|`VARNAME` is set to `:` (colon) and `OPTARG` contains the option-character in question|
## Using it
@ -212,7 +215,7 @@ while getopts ":a" opt; do
done
```
I put that into a file named `go_test.sh`, which is the name you\'ll see
I put that into a file named `go_test.sh`, which is the name you'll see
below in the examples.
Let's do some tests:

View File

@ -23,8 +23,8 @@ The basic procedure is simple: The script checks if a specific condition
doesn't start.
This article describes locking with common UNIX(r) tools. There are
other special locking tools available, But they\'re not standardized, or
worse yet, you can't be sure they\'re present when you want to run your
other special locking tools available, But they're not standardized, or
worse yet, you can't be sure they're present when you want to run your
scripts. **A tool designed for specifically for this purpose does the
job much better than general purpose code.**
@ -42,7 +42,7 @@ limits.
The best way to set a global lock condition is the UNIX(r) filesystem.
Variables aren't enough, as each process has its own private variable
space, but the filesystem is global to all processes (yes, I know about
chroots, namespaces, \... special case). You can \"set\" several things
chroots, namespaces, ... special case). You can "set" several things
in the filesystem that can be used as locking indicator:
- create files
@ -61,7 +61,7 @@ they are succesfully locked, and can operate without colliding. Setting
the timestamp is similar: One step to check the timespamp, a second step
to set the timestamp.
<WRAP center round tip 60%> [**Conclusion:**]{.underline} We need an
<WRAP center round tip 60%> <u>**Conclusion:**</u> We need an
operation that does the check and the locking in one step. </WRAP>
A simple way to get that is to create a **lock directory** - with the
@ -95,14 +95,14 @@ trapped. I am sure there there is a better solution than this
suggestion* --- **sn18** 2009/12/19 08:24*
**Note:** While perusing the Internet, I found some people asking if the
`mkdir` method works \"on all filesystems\". Well, let's say it should.
`mkdir` method works "on all filesystems". Well, let's say it should.
The syscall under `mkdir` is guarenteed to work atomicly in all cases,
at least on Unices. Two examples of problems are NFS filesystems and
filesystems on cluster servers. With those two scenarios, dependencies
exist related to the mount options and implementation. However, I
successfully use this simple method on an Oracle OCFS2 filesystem in a
4-node cluster environment. So let's just say \"it should work under
normal conditions\".
4-node cluster environment. So let's just say "it should work under
normal conditions".
Another atomic method is setting the `noclobber` shell option
(`set -C`). That will cause redirection to fail, if the file the

View File

@ -35,7 +35,7 @@ anymore.
### Operation modes
There are four basic operation modes to *list*, *read*, *write* and
*copy* archives. They\'re switched with combinations of `-r` and `-w`
*copy* archives. They're switched with combinations of `-r` and `-w`
command line options:
Mode RW-Options
@ -123,7 +123,7 @@ files to list or extract.
- if you specify the `-c` option, `pax` will invert the matches, i.e.
it matches all filenames **except** those matching the specified
patterns
- if no patterns are given, `pax` will \"match\" (list or extract) all
- if no patterns are given, `pax` will "match" (list or extract) all
files from the archive
- **To avoid conflicts with shell pathname expansion, it's wise to
quote patterns!**
@ -223,7 +223,7 @@ on the remote machine.
### Backup your daily work
[**Note:**]{.underline} `-T` is an extension and is not defined by
<u>**Note:**</u> `-T` is an extension and is not defined by
POSIX.
Say you have write-access to a fileserver mounted on your filesystem
@ -234,14 +234,14 @@ modified today:
pax -rw -T 0000 data/ /n/mybackups/$(date +%A)/
This is done using the `-T` switch, which normally allows you to specify
a time window, but in this case, only the start time which means \"today
at midnight\".
a time window, but in this case, only the start time which means "today
at midnight".
When you execute this \"very simple backup\" after your daily work, you
When you execute this "very simple backup" after your daily work, you
will have a copy of the modified files.
[**Note:**]{.underline} The `%A` format from `date` expands to the name
of the current day, localized, e.g. \"Friday\" (en) or \"Mittwoch\"
<u>**Note:**</u> The `%A` format from `date` expands to the name
of the current day, localized, e.g. "Friday" (en) or "Mittwoch"
(de).
The same, but with an archive, can be accomplished by:
@ -282,19 +282,19 @@ The -s command seen above can be used to exclude a file. The
substitution must result in a null string: For example, let's say that
you want to exclude all the CVS directories to create a source code
archive. We are going to replace the names containing /CVS/ with
nothing, note the .\* they are needed because we need to match the
nothing, note the `.*` they are needed because we need to match the
entire pathname.
pax -w -x ustar -f release.tar -s',.*/CVS/.*,,' myapplication
You can use several -s options, for instance, let's say you also want
to remove files ending in \~:
to remove files ending in `~`:
pax -w -x ustar -f release.tar -'s,.*/CVS/.*,,' -'s/.*~//' myapplication
This can also be done while reading an archive, for instance, suppose
you have an archive containing a \"usr\" and a \"etc\" directory but
that you want to extract only the \"usr\" directory:
you have an archive containing a "usr" and a "etc" directory but
that you want to extract only the "usr" directory:
pax -r -f archive.tar -s',^etc/.*,,' #the etc/ dir is not extracted

View File

@ -13,7 +13,7 @@ tags:
# Illustrated Redirection Tutorial
This tutorial is not a complete guide to redirection, it will not cover
here docs, here strings, name pipes etc\... I just hope it\'ll help you
here docs, here strings, name pipes etc... I just hope it'll help you
to understand what things like `3>&2`, `2>&1` or `1>&3-` do.
# stdin, stdout, stderr
@ -22,7 +22,7 @@ When Bash starts, normally, 3 file descriptors are opened, `0`, `1` and
`2` also known as standard input (`stdin`), standard output (`stdout`)
and standard error (`stderr`).
For example, with Bash running in a Linux terminal emulator, you\'ll
For example, with Bash running in a Linux terminal emulator, you'll
see:
# lsof +f g -ap $BASHPID -d 0,1,2
@ -54,7 +54,7 @@ connected to `/dev/pts/5`.
# Simple Redirections
## Output Redirection \"n> file\"
## Output Redirection "n&gt; file"
`>` is probably the simplest redirection.
@ -107,7 +107,7 @@ pointing to `file`. The command will then start with:
What will the command do with this descriptor? It depends. Often
nothing. We will see later why we might want other file descriptors.
## Input Redirection \"n< file\"
## Input Redirection "n&lt; file"
When you run a commandusing `command < file`, it changes the file
descriptor `0` so that it looks like:
@ -130,7 +130,7 @@ from the console.
As with `>`, `<` can be used to open a new file descriptor for reading,
`command 3<file`. Later we will see how this can be useful.
## Pipes \|
## Pipes |
What does this `|` do? Among other things, it connects the standard
output of the command on the left to the standard input of the command
@ -181,8 +181,8 @@ interesting example so we will use `ls /tmp/ doesnotexist 2>&1 | less`
--- +--------------+ --- +--------------+
Why is it called *duplicating*? Because after `2>&1`, we have 2 file
descriptors pointing to the same file. Take care not to call this \"File
Descriptor Aliasing\"; if we redirect `stdout` after `2>&1` to a file
descriptors pointing to the same file. Take care not to call this "File
Descriptor Aliasing"; if we redirect `stdout` after `2>&1` to a file
`B`, file descriptor `2` will still be opened on the file `A` where it
was. This is often misunderstood by people wanting to redirect both
standard input and standard output to the file. Continue reading for
@ -223,9 +223,10 @@ Similarly for output file descriptors, writing a line to file descriptor
`s` will append a line to a file as will writing a line to file
descriptor `t`.
<note tip>The syntax is somewhat confusing in that you would think
that the arrow would point in the direction of the copy, but it's
reversed. So it's `target>&source` effectively.</note>
!!! info "Tip"
The syntax is somewhat confusing in that you would think
that the arrow would point in the direction of the copy, but it's
reversed. So it's `target>&source` effectively.
So, as a simple example (albeit slightly contrived), is the following:
@ -235,7 +236,7 @@ So, as a simple example (albeit slightly contrived), is the following:
exec 1>&3 # Copy 3 back into 1
echo Done # Output to original stdout
## Order Of Redirection, i.e., \"> file 2>&1\" vs. \"2>&1 >file\"
## Order Of Redirection, i.e., "`> file 2>&1`" vs. "`2>&1 >file`"
While it doesn't matter where the redirections appears on the command
line, their order does matter. They are set up from left to right.
@ -323,7 +324,7 @@ Then it sees our duplication `2>&1`:
And voila, both `1` and `2` are redirected to file.
## Why sed 's/foo/bar/\' file >file Doesn't Work
## Why sed 's/foo/bar/' file >file Doesn't Work
This is a common error, we want to modify a file using something that
reads from a file and writes the result to `stdout`. To do this, we
@ -332,7 +333,7 @@ as we have seen, the redirections are setup before the command is
actually executed.
So **BEFORE** sed starts, standard output has already been redirected,
with the additional side effect that, because we used >, \"file\" gets
with the additional side effect that, because we used >, "file" gets
truncated. When `sed` starts to read the file, it contains nothing.
## exec
@ -447,8 +448,8 @@ it. It's probably better to do something like:
#we don't need 3 any more
I\'ve seen some people using this as a way to discard, say stderr, using
something like: command 2>&-. Though it might work, I\'m not sure if
I've seen some people using this as a way to discard, say stderr, using
something like: command 2>&-. Though it might work, I'm not sure if
you can expect all applications to behave correctly with a closed
stderr.
@ -598,11 +599,11 @@ original `stderr`.
# Syntax
I used to have trouble choosing between `0&<3` `3&>1` `3>&1` `->2`
`-<&0` `&-<0` `0<&-` etc\... (I think probably because the syntax is
`-<&0` `&-<0` `0<&-` etc... (I think probably because the syntax is
more representative of the result, i.e., the redirection, than what is
done, i.e., opening, closing, or duplicating file descriptors).
If this fits your situation, then maybe the following \"rules\" will
If this fits your situation, then maybe the following "rules" will
help you, a redirection is always like the following:
lhs op rhs
@ -612,18 +613,12 @@ help you, a redirection is always like the following:
the op is `<` then there is an implicit 0, if it's `>` or `>>`,
there is an implicit 1.
```{=html}
<!-- -->
```
- `op` is `<`, `>`, `>>`, `>|`, or `<>`:
- `<` if the file decriptor in `lhs` will be read, `>` if it will
be written, `>>` if data is to be appended to the file, `>|` to
overwrite an existing file or `<>` if it will be both read and
written.
```{=html}
<!-- -->
```
- `rhs` is the thing that the file descriptor will describe:
- It can be the name of a file, the place where another descriptor
goes (`&1`), or, `&-`, which will close the file descriptor.
@ -638,49 +633,34 @@ The shell is pretty loose about what it considers a valid redirect.
While opinions probably differ, this author has some (strong)
recommendations:
- **Always** keep redirections \"tightly grouped\" -- that is, **do
- **Always** keep redirections "tightly grouped" -- that is, **do
not** include whitespace anywhere within the redirection syntax
except within quotes if required on the RHS (e.g. a filename that
contains a space). Since shells fundamentally use whitespace to
delimit fields in general, it is visually much clearer for each
redirection to be separated by whitespace, but grouped in chunks
that contain no unnecessary whitespace.
```{=html}
<!-- -->
```
- **Do** always put a space between each redirection, and between the
argument list and the first redirect.
```{=html}
<!-- -->
```
- **Always** place redirections together at the very end of a command
after all arguments. Never precede a command with a redirect. Never
put a redirect in the middle of the arguments.
```{=html}
<!-- -->
```
- **Never** use the Csh `&>foo` and `>&foo` shorthand redirects. Use
the long form `>foo 2>&1`. (see: [obsolete](../scripting/obsolete.md))
```{=html}
<!-- -->
```bash
# Good! This is clearly a simple commmand with two arguments and 4 redirections
cmd arg1 arg2 <myFile 3<&1 2>/dev/null >&2
# Good!
{ cmd1 <<<'my input'; cmd2; } >someFile
# Bad. Is the "1" a file descriptor or an argument to cmd? (answer: it's the FD). Is the space after the herestring part of the input data? (answer: No).
# The redirects are also not delimited in any obvious way.
cmd 2>& 1 <<< stuff
# Hideously Bad. It's difficult to tell where the redirects are and whether they're even valid redirects.
# This is in fact one command with one argument, an assignment, and three redirects.
foo=bar<baz bork<<< blarg>bleh
```
# Good! This is clearly a simple commmand with two arguments and 4 redirections
cmd arg1 arg2 <myFile 3<&1 2>/dev/null >&2
# Good!
{ cmd1 <<<'my input'; cmd2; } >someFile
# Bad. Is the "1" a file descriptor or an argument to cmd? (answer: it's the FD). Is the space after the herestring part of the input data? (answer: No).
# The redirects are also not delimited in any obvious way.
cmd 2>& 1 <<< stuff
# Hideously Bad. It's difficult to tell where the redirects are and whether they're even valid redirects.
# This is in fact one command with one argument, an assignment, and three redirects.
foo=bar<baz bork<<< blarg>bleh
# Conclusion
@ -689,9 +669,9 @@ I hope this tutorial worked for you.
I lied, I did not explain `1>&3-`, go check the manual ;-)
Thanks to Stéphane Chazelas from whom I stole both the intro and the
example\....
example....
The intro is inspired by this introduction, you\'ll find a nice exercise
The intro is inspired by this introduction, you'll find a nice exercise
there too:
- [A Detailed Introduction to I/O and I/O

View File

@ -23,7 +23,7 @@ We have a simple **stat.sh** script:
echo "PYTHON LINES: $LINES"
This script evaluate the number of python files and the number of python
code lines in the files. We can use it like **./stat.sh <dir>**
code lines in the files. We can use it like **`./stat.sh <dir>`**
### Create testsuit

View File

@ -11,7 +11,7 @@ tags:
# List of shell options
This information was taken from a Bash version \"`4.1`\", every now and
This information was taken from a Bash version "`4.1`", every now and
then new options are added, so likely, this list isn't complete.
The shell-options can be set with the [shopt builtin
@ -21,35 +21,35 @@ command](../commands/builtin/shopt.md).
### autocd
Option: `autocd` Since: 4.0-alpha
------------- ------------------ ---------- -----------
Shell mode: interactive only Default: off
| Option: | `autocd` | Since: | 4.0-alpha |
|:------------|:-----------------|:---------|:----------|
| Shell mode: | interactive only | Default: | off |
If set, a command name that is the name of a directory is executed as if
it were the argument to the cd command.
### assoc_expand_once
Option: `assoc_expand_once` Since: 5.0-alpha
------------- --------------------- ---------- -----------
Shell mode: all Default: off
| Option: | `assoc_expand_once` | Since: | 5.0-alpha |
|:------------|:--------------------|:---------|:----------|
| Shell mode: | all | Default: | off |
If set, Bash attempts to expand associative array options only once.
### cdable_vars
Option: `cdable_vars` Since: unknown
------------- --------------- ---------- ---------
Shell mode: all Default: off
| Option: | `cdable_vars` | Since: | unknown |
|:------------|:--------------|:---------|:--------|
| Shell mode: | all | Default: | off |
Treat every **non-directory argument** to the `cd`-command as variable
name containing a directory to `cd` into.
### cdspell
Option: `cdspell` Since: unknown
------------- ------------------ ---------- ---------
Shell mode: interactive only Default: off
| Option: | `cdspell` | Since: | unknown |
|:------------|:-----------------|:---------|:--------|
| Shell mode: | interactive only | Default: | off |
If set, minor errors in the spelling of a directory component in a cd
command will be corrected. The errors checked for are transposed
@ -59,9 +59,9 @@ proceeds.
### checkhash
Option: `checkhash` Since: unknown
------------- ------------- ---------- ---------
Shell mode: all Default: off
| Option: | `checkhash` | Since: | unknown |
|:------------|:------------|:---------|:--------|
| Shell mode: | all | Default: | off |
If set, Bash checks that a command found in the hash table exists before
trying to execute it. If a hashed command no longer exists, a normal
@ -69,9 +69,9 @@ path search is performed.
### checkjobs
Option: `checkjobs` Since: 4.0-alpha
------------- ------------------ ---------- -----------
Shell mode: interactive only Default: off
| Option: | `checkjobs` | Since: | 4.0-alpha |
|:------------|:-----------------|:---------|:----------|
| Shell mode: | interactive only | Default: | off |
If set, Bash lists the status of any stopped and running jobs before
exiting an interactive shell. If any jobs are running, this causes the
@ -81,9 +81,9 @@ stopped.
### checkwinsize
Option: `checkwinsize` Since: unknown
------------- ---------------- ---------- ---------
Shell mode: all Default: on
| Option: | `checkwinsize` | Since: | unknown |
|:------------|:---------------|:---------|:--------|
| Shell mode: | all | Default: | on |
If set, Bash checks the window size after each command and, if
necessary, updates the values of the variables
@ -92,9 +92,9 @@ necessary, updates the values of the variables
### cmdhist
Option: `cmdhist` Since: unknown
------------- ----------- ---------- ---------
Shell mode: all Default: off
| Option: | `cmdhist` | Since: | unknown |
|:------------|:----------|:---------|:--------|
| Shell mode: | all | Default: | off |
If set, Bash attempts to save all lines of a multiple-line command in
the same history entry. This allows easy re-editing of multi-line
@ -102,65 +102,64 @@ commands.
### compat31
Option: `compat31` Since: 3.2
------------- ------------ ---------- -----
Shell mode: all Default: off
| Option: | `compat31` | Since: | 3.2 |
|:------------|:-----------|:---------|:----|
| Shell mode: | all | Default: | off |
Compatiblity mode for Bash 3.1
### compat32
Option: `compat32` Since: 4.0
------------- ------------ ---------- -----
Shell mode: all Default: off
| Option: | `compat32` | Since: | 4.0 |
|:------------|:-----------|:---------|:----|
| Shell mode: | all | Default: | off |
Compatiblity mode for Bash 3.2
### compat40
Option: `compat40` Since: 4.1-beta
------------- ------------ ---------- ----------
Shell mode: all Default: off
| Option: | `compat40` | Since: | 4.1-beta |
|:------------|:-----------|:---------|:---------|
| Shell mode: | all | Default: | off |
Compatiblity mode for Bash 4.0
### compat41
Option: `compat41` Since: 4.2-alpha
------------- ------------ ---------- -----------
Shell mode: all Default: off
| Option: | `compat41` | Since: | 4.2-alpha |
|:------------|:-----------|:---------|:----------|
| Shell mode: | all | Default: | off |
Compatiblity mode for Bash 4.1
### compat42
Option: `compat42` Since: 4.3-alpha
------------- ------------ ---------- -----------
Shell mode: all Default: off
| Option: | `compat42` | Since: | 4.3-alpha |
|:------------|:-----------|:---------|:----------|
| Shell mode: | all | Default: | off |
Compatiblity mode for Bash 4.2
### compat43
Option: `compat43` Since: 4.4-alpha
------------- ------------ ---------- -----------
Shell mode: all Default: off
| Option: | `compat43` | Since: | 4.4-alpha |
|:------------|:-----------|:---------|:----------|
| Shell mode: | all | Default: | off |
Compatiblity mode for Bash 4.3
### compat44
Option: `compat44` Since: 5.0-alpha
------------- ------------ ---------- -----------
Shell mode: all Default: off
| Option: | `compat44` | Since: | 5.0-alpha |
|:------------|:-----------|:---------|:----------|
| Shell mode: | all | Default: | off |
Compatiblity mode for Bash 4.4
### direxpand
Option: `direxpand` Since: 4.3-alpha
------------- ------------- ---------- ------------------------------------------------------------------------
Shell mode: all Default: off (unless changed on compile-time with `--enable-direxpand-default`)
| Option: | `direxpand` | Since: | 4.3-alpha |
|:------------|:------------|:---------|:-----------------------------------------------------------------------|
| Shell mode: | all | Default: | off (unless changed on compile-time with `--enable-direxpand-default`) |
If set, bash replaces directory names with the results of word expansion
when performing filename completion. This changes the contents of the
@ -169,27 +168,27 @@ user typed.
### dirspell
Option: `dirspell` Since: 4.0-alpha
------------- ------------ ---------- -----------
Shell mode: all Default: off
| Option: | `dirspell` | Since: | 4.0-alpha |
|:------------|:-----------|:---------|:----------|
| Shell mode: | all | Default: | off |
If set, Bash will perform spelling corrections on directory names to
match a glob.
### dotglob
Option: `dotglob` Since: unknown
------------- ----------- ---------- ---------
Shell mode: all Default: off
| Option: | `dotglob` | Since: | unknown |
|:------------|:----------|:---------|:--------|
| Shell mode: | all | Default: | off |
If set, Bash includes filenames beginning with a `.` (dot) in the
results of [pathname expansion](../syntax/expansion/globs.md).
### execfail
Option: `execfail` Since: unknown
------------- ----------------- ---------- ---------
Shell mode: non-interactive Default: off
| Option: | `execfail` | Since: | unknown |
|:------------|:----------------|:---------|:--------|
| Shell mode: | non-interactive | Default: | off |
If set, a non-interactive shell will not exit if it cannot execute the
file specified as an argument to the `exec`-builtin command. An
@ -197,26 +196,26 @@ interactive shell does not exit if `exec` fails.
### expand_aliases
Option: `expand_aliases` Since: unknown
------------- ------------------ ---------- -----------------------------------------
Shell mode: all Default: on (interactive), off (non-interactive)
| Option: | `expand_aliases` | Since: | unknown |
|:------------|:-----------------|:---------|:----------------------------------------|
| Shell mode: | all | Default: | on (interactive), off (non-interactive) |
If set, aliases are expanded. This option is enabled by default for
interactive shells.
### extdebug
Option: `extdebug` Since: 3.0-alpha
------------- ------------ ---------- -----------
Shell mode: all Default: off
| Option: | `extdebug` | Since: | 3.0-alpha |
|:------------|:-----------|:---------|:----------|
| Shell mode: | all | Default: | off |
If set, behavior intended for use by debuggers is enabled.
### extglob
Option: `extglob` Since: 2.02-alpha1
------------- ----------- ---------- -------------
Shell mode: all Default: off
| Option: | `extglob` | Since: | 2.02-alpha1 |
|:------------|:----------|:---------|:------------|
| Shell mode: | all | Default: | off |
If set, the extended [pattern matching](../syntax/pattern.md) features are
enabled. See the important note below under [Parser
@ -224,9 +223,9 @@ configurations](#parser_configurations).
### extquote
Option: `extquote` Since: 3.0-alpha (?)
------------- ------------ ---------- ---------------
Shell mode: all Default: on
| Option: | `extquote` | Since: | 3.0-alpha (?) |
|:------------|:-----------|:---------|:--------------|
| Shell mode: | all | Default: | on |
If set, `$'string'` and `$"string"` quoting is performed within
[parameter expansions](../syntax/pe.md) enclosed in double quotes. See the
@ -235,18 +234,18 @@ configurations](#parser_configurations).
### failglob
Option: `failglob` Since: 3.0-alpha
------------- ------------ ---------- -----------
Shell mode: all Default: off
| Option: | `failglob` | Since: | 3.0-alpha |
|:------------|:-----------|:---------|:----------|
| Shell mode: | all | Default: | off |
If set, patterns which fail to match filenames during pathname expansion
result in an error message.
### force_fignore
Option: `force_fignore` Since: 3.0-alpha
------------- ----------------- ---------- -----------
Shell mode: interactive Default: on
| Option: | `force_fignore` | Since: | 3.0-alpha |
|:------------|:----------------|:---------|:----------|
| Shell mode: | interactive | Default: | on |
If set, the suffixes specified by the
[FIGNORE](../syntax/shellvars.md#FIGNORE) shell variable cause words to be
@ -255,9 +254,9 @@ the only possible completions. This option is enabled by default.
### globasciiranges
Option: `globasciiranges` Since: 4.3-alpha
------------- ------------------- ---------- -----------------------------------
Shell mode: all Default: on (configurable at compile time)
| Option: | `globasciiranges` | Since: | 4.3-alpha |
|:------------|:------------------|:---------|:----------------------------------|
| Shell mode: | all | Default: | on (configurable at compile time) |
If set, range expressions used in pattern matching behave as if in the
traditional C locale when performing comparisons. That is, the current
@ -267,26 +266,26 @@ will collate together.
### globstar
Option: `globstar` Since: 4.0-alpha
------------- ------------ ---------- -----------
Shell mode: all Default: off
| Option: | `globstar` | Since: | 4.0-alpha |
|:------------|:-----------|:---------|:----------|
| Shell mode: | all | Default: | off |
If set, recursive globbing with `**` is enabled.
### gnu_errfmt
Option: `gnu_errfmt` Since: 3.0-alpha
------------- -------------- ---------- -----------
Shell mode: all Default: off
| Option: | `gnu_errfmt` | Since: | 3.0-alpha |
|:------------|:-------------|:---------|:----------|
| Shell mode: | all | Default: | off |
If set, shell error messages are written in the \"standard GNU error
message format\".
If set, shell error messages are written in the "standard GNU error
message format".
### histappend
Option: `histappend` Since: unknown
------------- ----------------- ---------- ---------
Shell mode: interactive (?) Default: off
| Option: | `histappend` | Since: | unknown |
|:------------|:----------------|:---------|:--------|
| Shell mode: | interactive (?) | Default: | off |
If set, the history list is appended to the file named by the value of
the [HISTFILE](../syntax/shellvars.md#HISTFILE) variable when the shell
@ -294,53 +293,53 @@ exits, rather than overwriting the file.
### histreedit
Option: `histreedit` Since: unknown
------------- ----------------- ---------- ---------
Shell mode: interactive (?) Default: off
| Option: | `histreedit` | Since: | unknown |
|:------------|:----------------|:---------|:--------|
| Shell mode: | interactive (?) | Default: | off |
If set, and readline is being used, a user is given the opportunity to
re-edit a failed history substitution.
### histverify
Option: `histverify` Since: unknown
------------- ----------------- ---------- ---------
Shell mode: interactive (?) Default: off
| Option: | `histverify` | Since: | unknown |
|:------------|:----------------|:---------|:--------|
| Shell mode: | interactive (?) | Default: | off |
Allow to review a history substitution result by loading the resulting
line into the editing buffer, rather than directly executing it.
### hostcomplete
Option: `hostcomplete` Since: 2.0-alpha3
------------- ----------------- ---------- ------------
Shell mode: interactive (?) Default: on
| Option: | `hostcomplete` | Since: | 2.0-alpha3 |
|:------------|:----------------|:---------|:-----------|
| Shell mode: | interactive (?) | Default: | on |
If set, Bash completion also completes hostnames. On by default.
### huponexit
Option: `huponexit` Since: 2.02-alpha1
------------- ------------------- ---------- -------------
Shell mode: interactive login Default: off
| Option: | `huponexit` | Since: | 2.02-alpha1 |
|:------------|:------------------|:---------|:------------|
| Shell mode: | interactive login | Default: | off |
If set, Bash will send the `SIGHUP` signal to all jobs when an
interactive login shell exits.
### interactive_comments
Option: `interactive_comments` Since: unknown
------------- ------------------------ ---------- ---------
Shell mode: interactive Default: on
| Option: | `interactive_comments` | Since: | unknown |
|:------------|:-----------------------|:---------|:--------|
| Shell mode: | interactive | Default: | on |
Allow [commenting](../scripting/basics.md#comments) in interactive shells, on
by default.
### lastpipe
Option: `lastpipe` Since: 4.2-alpha
------------- ------------ ---------- -----------
Shell mode: all Default: off
| Option: | `lastpipe` | Since: | 4.2-alpha |
|:------------|:-----------|:---------|:----------|
| Shell mode: | all | Default: | off |
If set, **and job control is not active**, the shell runs the last
command of a pipeline not executed in the background in the current
@ -348,9 +347,9 @@ shell environment.
### lithist
Option: `lithist` Since: unknown
------------- ------------- ---------- ---------
Shell mode: interactive Default: off
| Option: | `lithist` | Since: | unknown |
|:------------|:------------|:---------|:--------|
| Shell mode: | interactive | Default: | off |
If set, and the [#cmdhist](#cmdhist) option is enabled, multi-line
commands are saved to the history with embedded newlines rather than
@ -358,36 +357,36 @@ using semicolon separators where possible.
### localvar_inherit
Option: `localvar_inherit` Since: 5.0-alpha
------------- -------------------- ---------- -----------
Shell mode: all Default: off
| Option: | `localvar_inherit` | Since: | 5.0-alpha |
|:------------|:-------------------|:---------|:----------|
| Shell mode: | all | Default: | off |
If this option is set, a local variable inherits the value of a variable
with the same name at the nearest preceding scope.
### login_shell
Option: `login_shell` Since: 2.05a-alpha1
------------- --------------- ---------- --------------
Shell mode: all Default: n/a
| Option: | `login_shell` | Since: | 2.05a-alpha1 |
|:------------|:--------------|:---------|:-------------|
| Shell mode: | all | Default: | n/a |
The option is set when Bash is a login shell. This is a readonly option.
### mailwarn
Option: `mailwarn` Since: unknown
------------- ----------------- ---------- ---------
Shell mode: interactive (?) Default: off
| Option: | `mailwarn` | Since: | unknown |
|:------------|:----------------|:---------|:--------|
| Shell mode: | interactive (?) | Default: | off |
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.
since the last time it was checked, the message "The mail in mailfile
has been read" is displayed.
### no_empty_cmd_completion
Option: `mailwarn` Since: unknown
------------- ----------------- ---------- ---------
Shell mode: interactive (?) Default: off
| Option: | `mailwarn` | Since: | unknown |
|:------------|:----------------|:---------|:--------|
| Shell mode: | interactive (?) | Default: | off |
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
@ -395,45 +394,45 @@ line.
### nocaseglob
Option: `nocaseglob` Since: 2.02-alpha1
------------- -------------- ---------- -------------
Shell mode: all Default: off
| Option: | `nocaseglob` | Since: | 2.02-alpha1 |
|:------------|:-------------|:---------|:------------|
| Shell mode: | all | Default: | off |
If set, Bash matches filenames in a case-insensitive fashion when
performing pathname expansion.
### nocasematch
Option: `nocasematch` Since: 3.1-alpha1
------------- --------------- ---------- ------------
Shell mode: all Default: off
| Option: | `nocasematch` | Since: | 3.1-alpha1 |
|:------------|:--------------|:---------|:-----------|
| Shell mode: | all | Default: | off |
If set, Bash matches patterns in a case-insensitive fashion when
performing matching while executing `case` or `[[` conditional commands.
### nullglob
Option: `nullglob` Since: unknown
------------- ------------ ---------- ---------
Shell mode: all Default: off
| Option: | `nullglob` | Since: | unknown |
|:------------|:-----------|:---------|:--------|
| Shell mode: | all | Default: | off |
If set, Bash allows patterns which match no files to expand to a null
string, rather than themselves.
### progcomp
Option: `progcomp` Since: 2.04-alpha1
------------- ----------------- ---------- -------------
Shell mode: interactive (?) Default: on
|Option:|`progcomp`|Since:|2.04-alpha1|
|-------|----------|------|----------|
|Shell mode:|interactive (?)|Default:|on|
If set, the programmable completion facilities are enabled. This option
is enabled by default.
### promptvars
Option: `promptvars` Since: unknown
------------- -------------- ---------- ---------
Shell mode: interactive Default: on
|Option:|`promptvars`|Since:|unknown|
|-------|------------|------|-------|
|Shell mode:|interactive|Default:|on|
If set, prompt strings undergo parameter expansion, command
substitution, arithmetic expansion, and quote removal after being
@ -442,27 +441,27 @@ default.
### restricted_shell
Option: `restricted_shell` Since: 2.03-alpha
------------- -------------------- ---------- ------------
Shell mode: interactive (?) Default: off
|Option:|`restricted_shell`|Since:|2.03-alpha|
|-------|------------------|------|-------|
|Shell mode:|interactive (?)|Default:|off|
The option is set when Bash is a restricted shell. This is a readonly
option.
### shift_verbose
Option: `shift_verbose` Since: unknown
------------- ----------------- ---------- -----------------------
Shell mode: all Default: off, on in POSIX mode
|Option:|`shift_verbose`|Since:|unknown|
|-------|---------------|------|-------|
|Shell mode:|all|Default:|off, on in POSIX mode|
If set, the shift builtin prints an error message when the shift count
exceeds the number of positional parameters.
### sourcepath
Option: `sourcepath` Since: unknown
------------- -------------- ---------- ---------
Shell mode: all Default: on
|Option:|`sourcepath`|Since:|unknown|
|-------|------------|------|-------|
|Shell mode:|all|Default:|on|
If set, the source builtin command uses the value of PATH to find the
directory containing the file supplied as an argument. This option is
@ -470,9 +469,9 @@ enabled by default.
### syslog_history
Option: `syslog_history` Since: 5.0-alpha
------------- ------------------ ---------- -----------
Shell mode: unknown Default: off
|Option:|`syslog_history`|Since:|5.0-alpha|
|-------|----------------|------|--------|
|Shell mode:|unknown|Default:|off|
If set, the shell history is sent to syslog.
@ -481,9 +480,9 @@ syslog.
### xpg_echo
Option: `xpg_echo` Since: 2.04-beta1
------------- ------------ ---------- ------------
Shell mode: all Default: off
|Option:|`xpg_echo`|Since:|2.04-beta1|
|-------|----------|------|----------|
|Shell mode:|all|Default:|off|
If set, the `echo`-builtin command expands backslash-escape sequences by
default (POSIX, SUS, XPG).

View File

@ -5,48 +5,48 @@ in mind that this version is a snapshot, the bashphorisms are changed
here and there. Also, [another
snapshot](http://mywiki.wooledge.org/BashFAQ/064).
I think `greycat` was the first one who had the idea, but I\'m not sure.
I think `greycat` was the first one who had the idea, but I'm not sure.
Our bashphorisms can be queried from `greybot` using `!bN`, where `N` is
the bashphorism number.
And yes, these bashphorisms reflect the daily reality in `#bash`.
Number Bashphorism
-------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------
0 The questioner will never tell you what they are really doing the first time they ask.
1 The questioner's first description of the problem/question will be misleading.
2 The questioner will keep changing the question until it drives the helpers in the channel insane.
3 Offtopicness will continue until someone asks a bash question that falls under bashphorisms 1 and/or 2, and `greycat` gets pissed off.
4 The questioner will not read and apply the answers he is given but will instead continue to practice bashphorism #1 and bashphorism #2.
5 The ignorant will continually mis-educate the other noobies.
6 When given a choice of solutions, the newbie will always choose the wrong one.
7 The newbie will always find a reason to say, \"It doesn't work.\"
8 If you don't know to whom the bashphorism's referring, it's you.
9 All examples given by the questioner will be broken, misleading, wrong, and not representative of the actual question.
10 See B1
11 Please apply `(( % 10 ))` to the bashphorism value.
12 All logic is deniable; however, some logic will \*plonk\* you if you deny it.
13 Everyone ignores greycat when he is right. When he is wrong, it is !b1
14 The newbie doesn't actually know what he's asking. If he did, he wouldn't need to ask.
15 The more advanced you are, the more likely you are to be overcomplicating it.
16 The more beginner you are, the more likely you are to be overcomplicating it.
17 A newbie comes to #bash to get his script confirmed. He leaves disappointed.
18 The newbie will not accept the answer you give, no matter how right it is.
19 The newbie is a bloody loon.
20 The newbie will always have some excuse for doing it wrong.
21 When the newbie's question is ambiguous, the proper interpretation will be whichever one makes the problem the hardest to solve.
22 The newcomer will abuse the bot's factoid triggers for their own entertainment until someone gets annoyed enough to ask them to message it privately instead.
23 Everyone is a newcomer.
24 The newcomer will address greybot as if it were human.
25 The newbie won't accept any answer that uses practical or standard tools.
26 The newbie will not TELL you about this restriction until you have wasted half an hour.
27 The newbie will lie.
28 When the full horror of the newbie's true goal is revealed, the newbie will try to restate the goal to trick you into answering. Newbies are stupid.
29 It's always git. Or python virtualenv. Or docker. One of those pieces of shit. ALWAYS.
30 They won't show you the homework assignment. That would make it too easy.
31 Your teacher is a f\*\*king idiot.
32 The more horrifyingly wrong a proposed solution is, the more likely it will be used.
33 The newbie cannot explain what he is doing, or why. He will show you incomprehensible, nonworking code instead. What? You can't read his mind?!
|Number|Bashphorism|
|------|-----------|
|0|The questioner will never tell you what they are really doing the first time they ask.|
|1|The questioner's first description of the problem/question will be misleading.|
|2|The questioner will keep changing the question until it drives the helpers in the channel insane.|
|3|Offtopicness will continue until someone asks a bash question that falls under bashphorisms 1 and/or 2, and `greycat` gets pissed off.|
|4|The questioner will not read and apply the answers he is given but will instead continue to practice bashphorism #1 and bashphorism #2.|
|5|The ignorant will continually mis-educate the other noobies.|
|6|When given a choice of solutions, the newbie will always choose the wrong one.|
|7|The newbie will always find a reason to say, "It doesn't work."|
|8|If you don't know to whom the bashphorism's referring, it's you.|
|9|All examples given by the questioner will be broken, misleading, wrong, and not representative of the actual question.|
|10|See B1|
|11|Please apply `(( % 10 ))` to the bashphorism value.|
|12|All logic is deniable; however, some logic will *plonk* you if you deny it.|
|13|Everyone ignores greycat when he is right. When he is wrong, it is !b1|
|14|The newbie doesn't actually know what he's asking. If he did, he wouldn't need to ask.|
|15|The more advanced you are, the more likely you are to be overcomplicating it.|
|16|The more beginner you are, the more likely you are to be overcomplicating it.|
|17|A newbie comes to #bash to get his script confirmed. He leaves disappointed.|
|18|The newbie will not accept the answer you give, no matter how right it is.|
|19|The newbie is a bloody loon.|
|20|The newbie will always have some excuse for doing it wrong.|
|21|When the newbie's question is ambiguous, the proper interpretation will be whichever one makes the problem the hardest to solve.|
|22|The newcomer will abuse the bot's factoid triggers for their own entertainment until someone gets annoyed enough to ask them to message it privately instead.|
|23|Everyone is a newcomer.|
|24|The newcomer will address greybot as if it were human.|
|25|The newbie won't accept any answer that uses practical or standard tools.|
|26|The newbie will not TELL you about this restriction until you have wasted half an hour.|
|27|The newbie will lie.|
|28|When the full horror of the newbie's true goal is revealed, the newbie will try to restate the goal to trick you into answering. Newbies are stupid.|
|29|It's always git. Or python virtualenv. Or docker. One of those pieces of shit. ALWAYS.|
|30|They won't show you the homework assignment. That would make it too easy.|
|31|Your teacher is a f**king idiot.|
|32|The more horrifyingly wrong a proposed solution is, the more likely it will be used.|
|33|The newbie cannot explain what he is doing, or why. He will show you incomprehensible, nonworking code instead. What? You can't read his mind?!|
Please feel free to correct or extend this page whenever needed.

View File

@ -12,13 +12,14 @@ tags:
# Bash's behaviour
FIXME incomplete
!!! warning "FIXME"
incomplete
## Bash startup modes
### Login shell
As a \"login shell\", Bash reads and sets (executes) the user's profile
As a "login shell", Bash reads and sets (executes) the user's profile
from `/etc/profile` and one of `~/.bash_profile`, `~/.bash_login`, or
`~/.profile` (in that order, using the first one that's readable!).
@ -27,20 +28,20 @@ When a login shell exits, Bash reads and executes commands from the file
Why an extra login shell mode? There are many actions and variable sets
that only make sense for the initial user login. That's why all UNIX(r)
shells have (should have) a \"login\" mode.
shells have (should have) a "login" mode.
[**Methods to start Bash as a login shell:**]{.underline}
<u>**Methods to start Bash as a login shell:**</u>
- the first character of `argv[0]` is `-` (a hyphen): traditional
UNIX(r) shells start from the `login` binary
- Bash is started with the `-l` option
- Bash is started with the `--login` option
[**Methods to test for login shell mode:**]{.underline}
<u>**Methods to test for login shell mode:**</u>
- the shell option `login_shell` is set
[**Related switches:**]{.underline}
<u>**Related switches:**</u>
- `--noprofile` disables reading of all profile files
@ -49,7 +50,7 @@ shells have (should have) a \"login\" mode.
When Bash starts as an interactive non-login shell, it reads and
executes commands from `~/.bashrc`. This file should contain, for
example, aliases, since they need to be defined in every shell as
they\'re not inherited from the parent shell.
they're not inherited from the parent shell.
The feature to have a system-wide `/etc/bash.bashrc` or a similar
system-wide rc-file is specific to vendors and distributors that ship
@ -57,11 +58,11 @@ system-wide rc-file is specific to vendors and distributors that ship
system-wide rc file is to `source /etc/bashrc` from every user's
`~/.bashrc`.
[**Methods to test for interactive-shell mode:**]{.underline}
<u>**Methods to test for interactive-shell mode:**</u>
- the special parameter `$-` contains the letter `i` (lowercase I)
[**Related switches:**]{.underline}
<u>**Related switches:**</u>
- `-i` forces the interactive mode
- `--norc` disables reading of the startup files (e.g.
@ -83,7 +84,7 @@ used as the name of the startup file.
After the startup files are read, Bash enters the [POSIX(r) compatiblity
mode (for running, not for starting!)](#posix_run_mode).
[**Bash starts in `sh` compatiblity mode when:**]{.underline}
<u>**Bash starts in `sh` compatiblity mode when:**</u>
- the base filename in `argv[0]` is `sh` (:!: NB: `/bin/sh` may be
linked to `/bin/bash`, but that doesn't mean it acts like
@ -94,11 +95,11 @@ mode (for running, not for starting!)](#posix_run_mode).
When Bash is started in POSIX(r) mode, it follows the POSIX(r) standard
for startup files. In this mode, **interactive shells** expand the
[ENV](../syntax/shellvars.md#ENV) variable and commands are read and executed
from the file whose name is the expanded value.\
from the file whose name is the expanded value.
No other startup files are read. Hence, a non-interactive shell doesn't
read any startup files in POSIX(r) mode.
[**Bash starts in POSIX(r) mode when:**]{.underline}
<u>**Bash starts in POSIX(r) mode when:**</u>
- the commandline option `--posix` is specified
- the environment variable
@ -112,13 +113,13 @@ read any startup files in POSIX(r) mode.
Bash usually reads the first file found, when multiple choices are
given (for user files in `~/`)
Mode `/etc/profile` `~/.bash_profile` `~/.bash_login` `~/.profile` `~/.bashrc` `${ENV}`
----------------------- ---------------- ------------------- ----------------- -------------- ------------- ----------
Login shell X X X X - -
Interactive shell - - - - X -
SH compatible login X - - X - -
SH compatible - - - - - X
POSIX(r) compatiblity - - - - - X
|Mode|`/etc/profile`|`~/.bash_profile`|`~/.bash_login`|`~/.profile`|`~/.bashrc`|`${ENV}`|
|--|--|--|--|--|--|--|
|Login shell|✅|✅|✅|✅|🚫|🚫|
|Interactive shell|🚫|🚫|🚫|🚫|✅|🚫|
|SH compatible login|✅|🚫|🚫|✅|🚫|🚫|
|SH compatible|🚫|🚫|🚫|🚫|🚫|✅|
|POSIX(r) compatiblity|🚫|🚫|🚫|🚫|🚫|✅|
## Bash run modes
@ -304,9 +305,10 @@ and parsing (excerpt from a Bash maintainer's document):
Bash can be configured to be POSIX-conformant by default, by specifying
the `--enable-strict-posix-default' to `configure' when building.
FIXME help me to find out what breaks in POSIX(r) mode!
!!! warning "FIXME"
help me to find out what breaks in POSIX(r) mode!
[**The POSIX(r) mode can be switched on by:**]{.underline}
<u>**The POSIX(r) mode can be switched on by:**</u>
- Bash starting as `sh` (the basename of `argv[0]` is `sh`)
- starting Bash with the commandline option `--posix`
@ -314,7 +316,7 @@ FIXME help me to find out what breaks in POSIX(r) mode!
[POSIXLY_CORRECT](../syntax/shellvars.md#POSIXLY_CORRECT) is set
- the command `set -o posix`
[**Tests for the POSIX(r) mode:**]{.underline}
<u>**Tests for the POSIX(r) mode:**</u>
- the variable [SHELLOPTS](../syntax/shellvars.md#SHELLOPTS) contains
`posix` in its list
@ -330,7 +332,7 @@ like normal Bash with the following restrictions:
[PATH](../syntax/shellvars.md#PATH), [ENV](../syntax/shellvars.md#ENV) and
[BASH_ENV](../syntax/shellvars.md#BASH_ENV) can't be set or unset
- command names that contain a `/` (slash) can't be called (hence
you\'re limited to `PATH`)
you're limited to `PATH`)
- filenames containing a `/` (slash) can't be specified as argument
to the `source` or `.` builtin command
- filenames containing a `/` (slash) can't be specified as argument
@ -351,19 +353,19 @@ like normal Bash with the following restrictions:
- turning off restricted mode with `set +r` or `set +o restricted` is
(of course) forbidden
The \"-r\" restrictions are turned on **after** Bash has read its
The "-r" restrictions are turned on **after** Bash has read its
startup files.
When the command that is run is a shell script, then the restrictions
are **turned off** for the (sub-)shell that runs that shell script.
[**The restricted shell can be switched on by:**]{.underline}
<u>**The restricted shell can be switched on by:**</u>
- calling Bash as `rbash` (the basename of `argv[0]` is `rbash`)
- calling Bash with the `-r` option
- calling Bash with the `--restricted` option
[**Tests for restricted mode:**]{.underline}
<u>**Tests for restricted mode:**</u>
- the special parameter `$-` contains the letter `r` (lowercase R)
- the shell option `restricted_shell` is set and can be checked by the

View File

@ -22,56 +22,56 @@ For this topic, see also
- [shell_options](../internals/shell_options.md)
- [set](../commands/builtin/set.md)
Feature or change description Appeared in Bash version See also/remarks
--------------------------------- -------------------------- ---------------------------------------------------------------------------------
`posix` (for `set -o`) 1.14.0
`hostcomplete` 2.0-alpha3
`expand_aliases` 2.0
`huponexit` 2.02-alpha1
`nocaseglob` 2.02-alpha1
`extglob` 2.02-alpha1 together with extended globbing, KSH88
`restricted_shell` 2.03-alpha
`xpg_echo` 2.04-beta1
`progcomp` 2.04-alpha1
`no_empty_command_completion` 2.04
`login_shell` 2.05a-alpha1
`nolog` (for `set -o`) 2.05a
`gnu_errfmt` 3.0-alpha
`force_fignore` 3.0-alpha
`failglob` 3.0-alpha
`extquote` 3.0-alpha unsure -- verify!
`extdebug` 3.0-alpha
`pipefail` (for `set -o`) 3.0
`functrace` (for `set -o`) 3.0
`errtrace` (for `set -o`) 3.0
`nocasematch` 3.1-alpha1
`dirspell` 4.0-alpha
`globstar` 4.0-alpha
`checkjobs` 4.0-alpha
`autocd` 4.0-alpha
`set -e` effects more intuitive 4.0 not directly specified by POSIX, but in consensus with POSIX WG
`compat40` 4.1-beta
`lastpipe` 4.2-alpha only works with job control disabled
`compat41` 4.2-alpha
`globasciiranges` 4.3-alpha enable \"character range globbing\" to always act as if in `C` locale
`compat42` 4.3-alpha
`compat43` 4.4-alpha
`compat44` 5.0-alpha
`localvar_inherit` 5.0-alpha local variables inherit preceeding scope values if they have the same name
`syslog_history` 5.0-alpha send history lines to syslog (undocumented, default off) if syslog is supported
`assoc_expand_once` 5.0-alpha expand associative array subscripts only one
`globasciiranges` 5.0-beta New default: on (default may be configured at compile time)
`localvar_inherit` 5.0-beta guard code against inheriting from an incompatible data type
`checkwinsize` 5.0-beta2 New default: on
`shift_verbose` 5.0-beta2 Default on when in POSIX mode
|Feature or change description|Appeared in Bash version|See also/remarks|
|--|--|--|
|`posix` (for `set -o`)|1.14.0||
|`hostcomplete`|2.0-alpha3||
|`expand_aliases`|2.0||
|`huponexit`|2.02-alpha1||
|`nocaseglob`|2.02-alpha1||
|`extglob`|2.02-alpha1|together with extended globbing, KSH88|
|`restricted_shell`|2.03-alpha||
|`xpg_echo`|2.04-beta1||
|`progcomp`|2.04-alpha1||
|`no_empty_command_completion`|2.04||
|`login_shell`|2.05a-alpha1||
|`nolog` (for `set -o`)|2.05a||
|`gnu_errfmt`|3.0-alpha||
|`force_fignore`|3.0-alpha||
|`failglob`|3.0-alpha||
|`extquote`|3.0-alpha|unsure -- verify!|
|`extdebug`|3.0-alpha||
|`pipefail` (for `set -o`)|3.0||
|`functrace` (for `set -o`)|3.0||
|`errtrace` (for `set -o`)|3.0||
|`nocasematch`|3.1-alpha1||
|`dirspell`|4.0-alpha||
|`globstar`|4.0-alpha||
|`checkjobs`|4.0-alpha||
|`autocd`|4.0-alpha||
|`set -e` effects more intuitive|4.0|not directly specified by POSIX, but in consensus with POSIX WG|
|`compat40`|4.1-beta||
|`lastpipe`|4.2-alpha|only works with job control disabled|
|`compat41`|4.2-alpha||
|`globasciiranges`|4.3-alpha|enable "character range globbing" to always act as if in `C` locale|
|`compat42`|4.3-alpha||
|`compat43`|4.4-alpha||
|`compat44`|5.0-alpha||
|`localvar_inherit`|5.0-alpha|local variables inherit preceeding scope values if they have the same name|
|`syslog_history`|5.0-alpha|send history lines to syslog (undocumented, default off) if syslog is supported|
|`assoc_expand_once`|5.0-alpha|expand associative array subscripts only one|
|`globasciiranges`|5.0-beta|New default: on (default may be configured at compile time)|
|`localvar_inherit`|5.0-beta|guard code against inheriting from an incompatible data type|
|`checkwinsize`|5.0-beta2|New default: on|
|`shift_verbose`|5.0-beta2|Default on when in POSIX mode|
### General (all/many builtins)
Feature or change description Appeared in Bash version See also/remarks
----------------------------------------------------------------------- -------------------------- -----------------------------------------------------------------
generally return 2 on usage error 2.0
generally accept `--` (end of options) 2.0
(where applicable) implement a `-p` option to produce reusable output 2.0 `shopt` and `umask` builtins were fixed to support that in 2.02
|Feature or change description|Appeared in Bash version|See also/remarks|
|--|--|--|
|generally return 2 on usage error|2.0||
|generally accept `--` (end of options)|2.0||
|(where applicable) implement a `-p` option to produce reusable output|2.0|`shopt` and `umask` builtins were fixed to support that in 2.02|
### printf
@ -79,20 +79,20 @@ For this topic, see also
- [printf](../commands/builtin/printf.md)
Feature or change description Appeared in Bash version See also/remarks
------------------------------------------------------------- -------------------------- --------------------------------------------------------
new `printf` command 2.02-alpha1
respects `0..` and `0x..` prefixed numbers 2.04-beta1 consistency with arithmetic
POSIX(r) length specifiers `j`, `t` and `z` 2.05a-alpha1 ISO C99
POSIX(r) flag `'` 2.05a-alpha1
conversion `a` and `A` 2.05a-rc1 if provided by the underlying printf(3)
conversion `F` 2.05a-rc1
conversion `n` 2.05a-rc1
new option `-v` 3.1-alpha1
escape sequences `\"` and `\?` 3.0-beta1
modified option `-v` to assign to individual array elements 4.1-alpha
conversion `(...)T` 4.2-alpha support stftime(3) date/time format; uses current time
`\uNNNN` and `\UNNNNNNNN` escape sequences 4.2-alpha for: `printf`, `echo -e`, `$'...'`
|Feature or change description|Appeared in Bash version|See also/remarks|
|--|--|--|
|new `printf` command|2.02-alpha1||
|respects `0..` and `0x..` prefixed numbers|2.04-beta1|consistency with arithmetic|
|POSIX(r) length specifiers `j`, `t` and `z`|2.05a-alpha1|ISO C99|
|POSIX(r) flag `'`|2.05a-alpha1||
|conversion `a` and `A`|2.05a-rc1|if provided by the underlying printf(3)|
|conversion `F`|2.05a-rc1||
|conversion `n`|2.05a-rc1||
|new option `-v`|3.1-alpha1||
|escape sequences `\"` and `\?`|3.0-beta1||
|modified option `-v` to assign to individual array elements|4.1-alpha||
|conversion `(...)T`|4.2-alpha|support stftime(3) date/time format; uses current time|
|`\uNNNN` and `\UNNNNNNNN` escape sequences|4.2-alpha|for: `printf`, `echo -e`, `$'...'`|
### Conditional expressions and test command
@ -101,141 +101,141 @@ For this topic, see also
- [conditional_expression](../syntax/ccmd/conditional_expression.md)
- [classictest](../commands/classictest.md)
Feature or change description Appeared in Bash version See also/remarks
-------------------------------------------------------------------- -------------------------- --------------------------------------------------------------------------------------
`test`: `-o`, `==`, `<` and `>` 2.0
`test`: `-N` 2.02
`[[...]]`: new 2.02-alpha1 KSH93
`[[...]]`: regex support (`=~`) 3.0-alpha
`[[...]]`: quotable right-hand-side of `=~` forces string matching 3.2-alpha for consistency with pattern matching
`[[...]]`: `<` and `>` operators respect locale 4.1-alpha for consistency, since 4.1-beta: ensure you have set compatiblity to >4.0 (default)
`test`/`[`/`[[`: `-v` 4.2-alpha check if a variable is set
`test`/`[`/`[[`: `-v` 4.2-alpha support array syntax to check for elements
`test`/`[`/`[[`: `-N` accepts nanoseconds 5.1-alpha
`test`/`[`/`[[`: `-v` accepts positional parameters 5.1-alpha
|Feature or change description|Appeared in Bash version|See also/remarks|
|--|--|--|
|`test`: `-o`, `==`, `<` and `>`|2.0||
|`test`: `-N`|2.02||
|`[[...]]`: new|2.02-alpha1|KSH93|
|`[[...]]`: regex support (`=~`)|3.0-alpha||
|`[[...]]`: quotable right-hand-side of `=~` forces string matching|3.2-alpha|for consistency with pattern matching|
|`[[...]]`: `<` and `>` operators respect locale|4.1-alpha|for consistency, since 4.1-beta: ensure you have set compatiblity to \>4.0 (default)|
|`test`/`[`/`[[`: `-v`|4.2-alpha|check if a variable is set|
|`test`/`[`/`[[`: `-v`|4.2-alpha|support array syntax to check for elements|
|`test`/`[`/`[[`: `-N` accepts nanoseconds|5.1-alpha||
|`test`/`[`/`[[`: `-v` accepts positional parameters|5.1-alpha||
### Other builtins and keywords
Builtin Feature or change description Appeared in Bash version See also/remarks
----------------------- -------------------------------------------------------------------------------------------------------------------------------------------- -------------------------- -----------------------------------------------------------------------------------------------
`bashbug` new 1.14.0
`select` new 1.14.0
`disown` new 2.0
`shopt` new 2.0 [shopt](../commands/builtin/shopt.md)
`declare` new options `-a` and `-F` 2.0
`enable` builtin has basic plugin support (dlopen) 2.0
`exec` options `-l`, `-c` and `-a` 2.0
`read` options `-p`, `-e` and `-a` 2.0 [read](../commands/builtin/read.md)
`readonly` option `-a` 2.0 [arrays](../syntax/arrays.md)
`time` new keyword 2.0
`shopt` `-p` (reusable output) 2.02
`umask` `-p` (reusable output) 2.02
`complete` new 2.04-devel for and together with support for programmable completion
`compgen` new 2.04-devel for and together with support for programmable completion
`read` options `-t`, `-n`, `-d`, `-s` 2.04-devel [read](../commands/builtin/read.md)
`for ((...;...;...))` new 2.04-devel KSH93
`set` print shell functions in a format reusable as input 2.05-beta1
`for` allow an empty word list 2.05a-alpha1
`read` new option `-u` 2.05b-alpha1 [read](../commands/builtin/read.md)
`caller` new 3.0 [caller](../commands/builtin/caller.md)
`coproc` new 4.0-alpha
`declare` new options `-l` and `-u` 4.0-alpha together with case-changing expansion forms
`case` new action list terminators \'\';;& and \'\';& 4.0-alpha ksh93: only `;&`. zsh and mksh: `;|`. mksh: all 4, (`;;&` is undocumented Bash compatibility)
`read` changed `-t` (fractional seconds) 4.0-alpha
`mapfile` new 4.0-alpha
`read` new option `-i` 4.0-alpha
`compopt` new 4.0-alpha
`read` modified option `-t` to test for data 4.0-beta
`read` new option `-N` 4.1-alpha
`mapfile` changed behaviour regarding history spamming 4.1-alpha
`declare` new option `-g` 4.2-alpha
`mapfile` calls the callback with an additional argument: The line (data) 4.2-alpha
`cd` new option `-e` 4.2-alpha
`echo` `\uNNNN` and `\UNNNNNNNN` escape sequences 4.2-alpha for: `printf`, `echo -e`, `$'...'`
`exec` option `-a` to give a `argv[0]` string 4.2-alpha
`time` allowed as a command by itself to display timing values of the shell and its children 4.2-alpha POSIX change
`help` `help` now searches exact topic-strings (i.e. `help read` won't find `readonly` anymore) 4.3-alpha
`return` accept negative values as return value (e.g. `return -1` will show as (8 bit) 255 in the caller) 4.3-alpha
`exit` accept negative values as return value (e.g. `return -1` will show as (8 bit) 255 in the caller) 4.3-alpha
`read` `read` skips `NUL` (ASCII Code 0) in input 4.3-alpha
`declare` new option `-n`/`+n` to support nameref variable type 4.3-alpha
`wait` new option `-n` to wait for the next background job to finish, returning its exit status. 4.3-alpha
`read` `read` checks first variable argument for validity before trying to read inout 4.3-beta
`help` attempts substring matching (as it did through bash-4.2) if exact string matching fails 4.3-beta2
`fc` interprets option `-0` (zero) as the current command line 4.3-beta2
`cd` new option `-@` to browse a file's extended attributes (on systems that support `O_XATTR`) 4.3-rc1
`kill` new option `-L` (upper case ell) to list signals like the normal lowercase option `-l` (compatiblity with some standalone `kill` commands) 4.4-beta
`mapfile` new option `-d` 4.4-alpha
`wait` new option `-f` 5.0-alpha
`history` option `-d` allows negative numbers to index from the end of the history list 5.0-alpha
`umask` allows modes greater than octal 777 5.0-alpha
`times` honors current locale settings when printing decimal points 5.0-alpha
`kill` New options `-n SIGNUMBER` and `-s SIGNAME` 5.0-beta2 [kill](../commands/builtin/kill.md)
`select` Support for an empty wordlist following `in` 5.0-beta2
`read` Option `-e` (use ReadLine to obtain input) now works with arbitrary file descriptors (given by `-u` option) 5.1-alpha
`trap` `-p` option prints signals with SIG_DFL/SIG_IGN on shell start (POSIX mode) 5.1-alpha
`unset` automatically tries to unset a function if the given name is an invalid variable name 5.1-aplha
`wait` option `-n` now accepts a list of jobs 5.1-alpha
`wait` new option `-p NAME` to store PID/JobID (useful when waiting for a list of jobs) 5.1-alpha
`local` new option `-p` to print local variables in the current scope 5.1-alpha
`ulimit` new option `-R` to get/set `RLIMIT_RTTIME` resource 5.1-alpha
|Builtin|Feature or change description|Appeared in Bash version|See also/remarks|
|--|--|--|--|
|`bashbug`|new|1.14.0||
|`select`|new|1.14.0||
|`disown`|new|2.0||
|`shopt`|new|2.0|[shopt](../commands/builtin/shopt.md)|
|`declare`|new options `-a` and `-F`|2.0||
|`enable`|builtin has basic plugin support (dlopen)|2.0||
|`exec`|options `-l`, `-c` and `-a`|2.0||
|`read`|options `-p`, `-e` and `-a`|2.0|[read](../commands/builtin/read.md)|
|`readonly`|option `-a`|2.0|[arrays](../syntax/arrays.md)|
|`time`|new keyword|2.0||
|`shopt`|`-p` (reusable output)|2.02||
|`umask`|`-p` (reusable output)|2.02||
|`complete`|new|2.04-devel|for and together with support for programmable completion|
|`compgen`|new|2.04-devel|for and together with support for programmable completion|
|`read`|options `-t`, `-n`, `-d`, `-s`|2.04-devel|[read](../commands/builtin/read.md)|
|`for ((...;...;...))`|new|2.04-devel|KSH93|
|`set`|print shell functions in a format reusable as input|2.05-beta1||
|`for`|allow an empty word list|2.05a-alpha1||
|`read`|new option `-u`|2.05b-alpha1|[read](../commands/builtin/read.md)|
|`caller`|new|3.0|[caller](../commands/builtin/caller.md)|
|`coproc`|new|4.0-alpha||
|`declare`|new options `-l` and `-u`|4.0-alpha|together with case-changing expansion forms|
|`case`|new action list terminators '';;& and '';&|4.0-alpha|ksh93: only `;&`. zsh and mksh: `;|`. mksh: all 4, (`;;&` is undocumented Bash compatibility)|
|`read`|changed `-t` (fractional seconds)|4.0-alpha||
|`mapfile`|new|4.0-alpha||
|`read`|new option `-i`|4.0-alpha||
|`compopt`|new|4.0-alpha||
|`read`|modified option `-t` to test for data|4.0-beta||
|`read`|new option `-N`|4.1-alpha||
|`mapfile`|changed behaviour regarding history spamming|4.1-alpha||
|`declare`|new option `-g`|4.2-alpha||
|`mapfile`|calls the callback with an additional argument: The line (data)|4.2-alpha||
|`cd`|new option `-e`|4.2-alpha||
|`echo`|`\uNNNN` and `\UNNNNNNNN` escape sequences|4.2-alpha|for: `printf`, `echo -e`, `$'...'`|
|`exec`|option `-a` to give a `argv[0]` string|4.2-alpha||
|`time`|allowed as a command by itself to display timing values of the shell and its children|4.2-alpha|POSIX change|
|`help`|`help` now searches exact topic-strings (i.e. `help read` won't find `readonly` anymore)|4.3-alpha||
|`return`|accept negative values as return value (e.g. `return -1` will show as (8 bit) 255 in the caller)|4.3-alpha||
|`exit`|accept negative values as return value (e.g. `return -1` will show as (8 bit) 255 in the caller)|4.3-alpha||
|`read`|`read` skips `NUL` (ASCII Code 0) in input|4.3-alpha||
|`declare`|new option `-n`/`+n` to support nameref variable type|4.3-alpha||
|`wait`|new option `-n` to wait for the next background job to finish, returning its exit status.|4.3-alpha||
|`read`|`read` checks first variable argument for validity before trying to read inout|4.3-beta||
|`help`|attempts substring matching (as it did through bash-4.2) if exact string matching fails|4.3-beta2||
|`fc`|interprets option `-0` (zero) as the current command line|4.3-beta2||
|`cd`|new option `-@` to browse a file's extended attributes (on systems that support `O_XATTR`)|4.3-rc1||
|`kill`|new option `-L` (upper case ell) to list signals like the normal lowercase option `-l` (compatiblity with some standalone `kill` commands)|4.4-beta||
|`mapfile`|new option `-d`|4.4-alpha||
|`wait`|new option `-f`|5.0-alpha||
|`history`|option `-d` allows negative numbers to index from the end of the history list|5.0-alpha||
|`umask`|allows modes greater than octal 777|5.0-alpha||
|`times`|honors current locale settings when printing decimal points|5.0-alpha||
|`kill`|New options `-n SIGNUMBER` and `-s SIGNAME`|5.0-beta2|[kill](/commands/builtin/kill)|
|`select`|Support for an empty wordlist following `in`|5.0-beta2||
|`read`|Option `-e` (use ReadLine to obtain input) now works with arbitrary file descriptors (given by `-u` option)|5.1-alpha||
|`trap`|`-p` option prints signals with SIG_DFL/SIG_IGN on shell start (POSIX mode)|5.1-alpha||
|`unset`|automatically tries to unset a function if the given name is an invalid variable name|5.1-aplha||
|`wait`|option `-n` now accepts a list of jobs|5.1-alpha||
|`wait`|new option `-p NAME` to store PID/JobID (useful when waiting for a list of jobs)|5.1-alpha||
|`local`|new option `-p` to print local variables in the current scope|5.1-alpha||
|`ulimit`|new option `-R` to get/set `RLIMIT_RTTIME` resource|5.1-alpha||
## Builtin variables
Feature or change description Appeared in Bash version See also
--------------------------------------------------- -------------------------- ----------------------------------------------------------------------------------
`HISTCMD` 1.14.0 interactive usage
`PS1`, `PS2`, `PATH`, and `IFS` are unsettable 2.0
`DIRSTACK` array variable 2.0
`PIPESTATUS` array variable 2.0
`BASH_VERSINFO` array variable 2.0
`HOSTNAME` 2.0
`SHELLOPTS` 2.0
`MACHTYPE` 2.0
`GLOBIGNORE` 2.0
`HISTIGNORE` 2.0
respect `LC_ALL` 2.0
respect `LC_MESSAGES` 2.0
respect `LC_CTYPE` 2.0
respect `LC_COLLATE` 2.0
respect `LANG` 2.0
`GROUPS` array variable 2.01
`GROUPS` unsettable/takes (discarded) assignments 2.04
`FUNCNAME` 2.04
respect `LC_NUMERIC` 2.04
`TMOUT` 2.05b
`BASH_REMATCH` 3.0 together with regex support in `[[...]]`
`BASH_ARGC` 3.0 debugger support
`BASH_ARGV` 3.0 debugger support
`BASH_SOURCE` 3.0 debugger support
`BASH_LINENO` 3.0 debugger support
`BASH_SUBSHELL` 3.0 debugger support
`BASH_EXECUTION_STRING` 3.0 debugger support
`BASH_COMMAND` 3.0 debugger support
`HISTTIMEFORMAT` 3.0
`COMP_WORDBREAKS` 3.0
respect `LC_TIME` 3.1
`BASHPID` 4.0-alpha Added to mksh R41.
`PROMPT_DIRTRIM` 4.0
`BASH_XTRACEFD` 4.1-alpha
`BASHOPTS` 4.1-alpha
`FUNCNEST` 4.2-alpha
`HISTSIZE` 4.3-alpha can be set to negative values for unlimited history length
`HISTFILESIZE` 4.3-alpha can be set to negative values for unlimit history file size
`CHILD_MAX` 4.3-alpha max. number of exit status of children the shell remembers
`BASH_COMPAT` 4.3-alpha set shell compatiblity levels
`EPOCHSECONDS` 5.0-alpha expands to the time in seconds since Unix epoch
`EPOCHREALTIME` 5.0-alpha expands to the time in seconds since Unix epoch with microsecond granularity
`BASH_ARGV0` 5.0-alpha get/set `$0`
`PATH` 5.0-alpha Possibility to set a static path for use in a restricted shell (at compile time)
`HISTSIZE` 5.0-beta Default can now be set at runtime
`SRANDOM` 5.1-alpha New random generator for 32bit numbers (using various methods in the backend)
`ARGV0` 5.1-alpha Respected when set in initial shell environment, then initially used to set `$0`
`BASH_REMATCH` 5.1-alpha Not readonly anymore
`PROMPT_COMMANDS` 5.1-alpha New array variable. List of commands to be executed like `PROMPT_COMMAND`
`SECONDS` 5.1-alpha Assignment using arithmetic expressions (is nominally an integer variabnle)
`RANDOM` 5.1-alpha Assignment using arithmetic expressions (is nominally an integer variabnle)
`LINENO` 5.1-alpha Not an integer variabe
|Feature or change description|Appeared in Bash version|See also|
|--|--|--|
|`HISTCMD`|1.14.0|interactive usage|
|`PS1`, `PS2`, `PATH`, and `IFS` are unsettable|2.0||
|`DIRSTACK` array variable|2.0||
|`PIPESTATUS` array variable|2.0||
|`BASH_VERSINFO` array variable|2.0||
|`HOSTNAME`|2.0||
|`SHELLOPTS`|2.0||
|`MACHTYPE`|2.0||
|`GLOBIGNORE`|2.0||
|`HISTIGNORE`|2.0||
|respect `LC_ALL`|2.0||
|respect `LC_MESSAGES`|2.0||
|respect `LC_CTYPE`|2.0||
|respect `LC_COLLATE`|2.0||
|respect `LANG`|2.0||
|`GROUPS` array variable|2.01||
|`GROUPS` unsettable/takes (discarded) assignments|2.04||
|`FUNCNAME`|2.04||
|respect `LC_NUMERIC`|2.04||
|`TMOUT`|2.05b||
|`BASH_REMATCH`|3.0|together with regex support in `[[...]]`|
|`BASH_ARGC`|3.0|debugger support|
|`BASH_ARGV`|3.0|debugger support|
|`BASH_SOURCE`|3.0|debugger support|
|`BASH_LINENO`|3.0|debugger support|
|`BASH_SUBSHELL`|3.0|debugger support|
|`BASH_EXECUTION_STRING`|3.0|debugger support|
|`BASH_COMMAND`|3.0|debugger support|
|`HISTTIMEFORMAT`|3.0||
|`COMP_WORDBREAKS`|3.0||
|respect `LC_TIME`|3.1||
|`BASHPID`|4.0-alpha|Added to mksh R41.|
|`PROMPT_DIRTRIM`|4.0||
|`BASH_XTRACEFD`|4.1-alpha||
|`BASHOPTS`|4.1-alpha||
|`FUNCNEST`|4.2-alpha||
|`HISTSIZE`|4.3-alpha|can be set to negative values for unlimited history length|
|`HISTFILESIZE`|4.3-alpha|can be set to negative values for unlimit history file size|
|`CHILD_MAX`|4.3-alpha|max. number of exit status of children the shell remembers|
|`BASH_COMPAT`|4.3-alpha|set shell compatiblity levels|
|`EPOCHSECONDS`|5.0-alpha|expands to the time in seconds since Unix epoch|
|`EPOCHREALTIME`|5.0-alpha|expands to the time in seconds since Unix epoch with microsecond granularity|
|`BASH_ARGV0`|5.0-alpha|get/set `$0`|
|`PATH`|5.0-alpha|Possibility to set a static path for use in a restricted shell (at compile time)|
|`HISTSIZE`|5.0-beta|Default can now be set at runtime|
|`SRANDOM`|5.1-alpha|New random generator for 32bit numbers (using various methods in the backend)|
|`ARGV0`|5.1-alpha|Respected when set in initial shell environment, then initially used to set `$0`|
|`BASH_REMATCH`|5.1-alpha|Not readonly anymore|
|`PROMPT_COMMANDS`|5.1-alpha|New array variable. List of commands to be executed like `PROMPT_COMMAND`|
|`SECONDS`|5.1-alpha|Assignment using arithmetic expressions (is nominally an integer variabnle)|
|`RANDOM`|5.1-alpha|Assignment using arithmetic expressions (is nominally an integer variabnle)|
|`LINENO`|5.1-alpha|Not an integer variabe|
## Quoting, expansions, substitutions and related
@ -243,40 +243,40 @@ For this topic, see also
- [pe](../syntax/pe.md).
Feature or change description Appeared in Bash version Remarks
------------------------------------------------------------------------------------------------------ -------------------------- ---------------------------------------------------------------------------------------------------------------
Support for integer-indexed arrays 2.0 relevant builtins also got array support
`${PARAMETER//PATTERN/REPLACEMENT}` 2.0
`${PARAMETER:OFFSET:LENGTH}` 2.0
`${!PARAMETER}` (indirection) 2.0
`$"..."` (localized strings) 2.0
`$'...'` (ANSI-C-like strings) 2.0
`\xNNN` in `$'...'` (and `echo -e`) 2.02-alpha1
`$(< FILENAME)` (file content) 2.02-alpha1
globbing (`fnmatch()`) capable of POSIX(r) character classes etc. 2.02-alpha1
extended globbing 2.02-alpha1 KSH88
globbing inside array mass-assignment: `ARRAY=(*.txt)` 2.03-alpha
`$'...\'...'` escaped single quote inside ANSI-C-like strings 2.04-devel KSH93
`${!PREFIX*}` (parameter name expansion) 2.04 KSH93
`$'...'` expands `\cx` (Control-x) 2.05b
`[:class:]` syntax for pattern matching 2.05b KSH93
`${!ARRAY[@]}` (array index expansion) 3.0-alpha KSH93
`{x..y}` (range brace expansion) 3.0-alpha
`$'...'` expands `\xNNN` (Hexdigits) 3.0
`+=` operator for arrays and strings 3.1-alpha1
`${PARAMETER//PATTERN/REPLACEMENT}` behaviour changed 3.2-alpha anchoring for global substitution is no longer allowed, changes the way old syntax may work
`${@:0:x}` includes `$0` 4.0-alpha
Support for associative arrays 4.0-alpha relevant builtins also got associative array support
case modification operators for expansions 4.0-alpha
`{0x..0y}` (zeropadding brace expansion) 4.0-alpha
numerically indexed arrays can be accessed (on expansion time) from the end using negative indexes 4.1-alpha
`\uNNNN` and `\uNNNNNNNN` in `$'...'` 4.2-alpha for: `printf`, `echo -e`, `$'...'`
`${PARAMETER:OFFSET:LENGTH}`: Negative `LENGTH` values are used as offset from the end of the string 4.2-alpha Substrings only for Bash and ksh93. Works also for argument expansions in zsh. ksh93 can use `${arr[n..-m]}`.
Word expansions like `${foo##bar}` understand indirect variable references 4.3-beta
Transformations 4.4
Process substitution now works in POSIX mode 5.1-alpha
New transformations: `U`, `u`, `L` 5.1-alpha Case-transformation
New transformation: `K` 5.1-alpha Display associative arrays as key/value pairs
|Feature or change description|Appeared in Bash version|Remarks|
|--|--|--|
|Support for integer-indexed arrays|2.0|relevant builtins also got array support|
|`${PARAMETER//PATTERN/REPLACEMENT}`|2.0||
|`${PARAMETER:OFFSET:LENGTH}`|2.0||
|`${!PARAMETER}` (indirection)|2.0||
|`$"..."` (localized strings)|2.0||
|`$'...'` (ANSI-C-like strings)|2.0||
|`\xNNN` in `$'...'` (and `echo -e`)|2.02-alpha1||
|`$(< FILENAME)` (file content)|2.02-alpha1||
|globbing (`fnmatch()`) capable of POSIX(r) character classes etc.|2.02-alpha1||
|extended globbing|2.02-alpha1|KSH88|
|globbing inside array mass-assignment: `ARRAY=(*.txt)`|2.03-alpha||
|`$'...\'...'` escaped single quote inside ANSI-C-like strings|2.04-devel|KSH93|
|`${!PREFIX*}` (parameter name expansion)|2.04|KSH93|
|`$'...'` expands `\cx` (Control-x)|2.05b||
|`[:class:]` syntax for pattern matching|2.05b|KSH93|
|`${!ARRAY[@]}` (array index expansion)|3.0-alpha|KSH93|
|`{x..y}` (range brace expansion)|3.0-alpha||
|`$'...'` expands `\xNNN` (Hexdigits)|3.0||
|`+=` operator for arrays and strings|3.1-alpha1||
|`${PARAMETER//PATTERN/REPLACEMENT}` behaviour changed|3.2-alpha|anchoring for global substitution is no longer allowed, changes the way old syntax may work|
|`${@:0:x}` includes `$0`|4.0-alpha||
|Support for associative arrays|4.0-alpha|relevant builtins also got associative array support|
|case modification operators for expansions|4.0-alpha||
|`{0x..0y}` (zeropadding brace expansion)|4.0-alpha||
|numerically indexed arrays can be accessed (on expansion time) from the end using negative indexes|4.1-alpha||
|`\uNNNN` and `\uNNNNNNNN` in `$'...'`|4.2-alpha|for: `printf`, `echo -e`, `$'...'`|
|`${PARAMETER:OFFSET:LENGTH}`: Negative `LENGTH` values are used as offset from the end of the string|4.2-alpha|Substrings only for Bash and ksh93. Works also for argument expansions in zsh. ksh93 can use `${arr[n..-m]}`.|
|Word expansions like `${foo##bar}` understand indirect variable references|4.3-beta||
|Transformations|4.4||
|Process substitution now works in POSIX mode|5.1-alpha||
|New transformations: `U`, `u`, `L`|5.1-alpha|Case-transformation|
|New transformation: `K`|5.1-alpha|Display associative arrays as key/value pairs|
## Arithmetic
@ -285,15 +285,15 @@ For this topic, see also
- [arith_expr](../syntax/arith_expr.md)
- [arith](../syntax/expansion/arith.md)
Feature or change description Appeared in Bash version Remarks
-------------------------------------------- -------------------------- -------------------------------------------
`((...))` 2.0-beta2 KSH93
ternary operator 2.0
base 64 integer constants 2.0 the max. base before is unknown. Anybody?
deprecated `$[...]` in favor of `$((...))` 2.0
exponentiaition operator (`**`) 2.02-alpha1
comma operator `EXPR,EXPR` 2.04-devel
pre- and postfix operators 2.04-devel
|Feature or change description|Appeared in Bash version|Remarks|
|--|--|--|
|`((...))`|2.0-beta2|KSH93|
|ternary operator|2.0||
|base 64 integer constants|2.0|the max. base before is unknown. Anybody?|
|deprecated `$[...]` in favor of `$((...))`|2.0||
|exponentiaition operator (`**`)|2.02-alpha1||
|comma operator `EXPR,EXPR`|2.04-devel||
|pre- and postfix operators|2.04-devel||
## Redirection and related
@ -301,33 +301,33 @@ For this topic, see also
- [redirection](../syntax/redirection.md)
Feature or change description Appeared in Bash version Remarks
--------------------------------------------------------------------------------------- -------------------------- ---------
socket redirection (`/dev/tcp/`, `/dev/udp/`) 2.04-devel
OS/filesystem-independent support for `/dev/std(in|out|err)` and `/dev/fd/*` 2.04
socket redirection accepts service names 2.05
`[n]<&word-` and `[n]>&word-` FD-duplicate/closing 2.05b-alpha1 KSH93
Here strings: `<<< WORD` 2.05b-alpha1
`|&` (synonym for `2>&1 |`) 4.0-alpha
`&>>` (equiv. to `>>FILE 2>&1`) 4.0-alpha
`{varname}` style automatic file descriptor allocation 4.1-alpha ksh93
`{varname[idx]}` fd allocation accepts array subscripts and special-meaning variables 4.3-alpha ksh93
|Feature or change description|Appeared in Bash version|Remarks|
|--|--|--|
|socket redirection (`/dev/tcp/`, `/dev/udp/`)|2.04-devel||
|OS/filesystem-independent support for `/dev/std(in|out|err)` and `/dev/fd/*`|2.04||
|socket redirection accepts service names|2.05||
|`[n]<&word-` and `[n]>&word-` FD-duplicate/closing|2.05b-alpha1|KSH93|
|Here strings: `<<< WORD`|2.05b-alpha1||
|`|&` (synonym for `2>&1|`)|4.0-alpha||
|`&>>` (equiv. to `>>FILE 2>&1`)|4.0-alpha||
|`{varname}` style automatic file descriptor allocation|4.1-alpha|ksh93|
|`{varname[idx]}` fd allocation accepts array subscripts and special-meaning variables|4.3-alpha|ksh93|
## Misc
Feature or change description Appeared in Bash version See also/remarks
------------------------------------------------------------------------------------------------- -------------------------- ------------------------------------------------------------------------------------------------------------------------------------------
`DEBUG` trap 2.0
`ERR` trap 2.05a KSH93
Support for multibyte characters: Unicode / UTF8 2.05b
`RETURN` trap 3.0 ksh93 `EXIT` trap evaluates in caller scope (for `function name {`). Bash `RETURN` in same scope.
`command_not_found_handle` handler function 4.0-alpha
official introduction of switchable \"compatiblity levels\" 4.0-alpha `compat31` was introduced in a 3.2 version, mainly because of the incompatibilities that were introduced by the changed `=~` operator
`[[...]]` and `((...))` conditional commands are subject to the `ERR` trap and `set -e` feature 4.1-alpha
ACL support for file status checks 4.1-alpha
Assignment to negative array indices 4.3-alpha ksh93, zsh
`declare`/`typeset -n` 4.3-alpha Support for nameref variable type, a variable referencing another one by name
shells started to run process substitutions now run any trap set on `EXIT` 4.3-beta
process substitution does not inherit the `v` flag 5.0-alpha
`ERR` trap 5.0-alpha Reports more reliable line numbers
Variable assignment 5.0-beta Assignments preceeding a special builtin that chages variable attributes are not propagated back unless compatiblity mode is 44 or lower
|Feature or change description|Appeared in Bash version|See also/remarks|
|--|--|--|
|`DEBUG` trap|2.0||
|`ERR` trap|2.05a|KSH93|
|Support for multibyte characters: Unicode / UTF8|2.05b||
|`RETURN` trap|3.0|ksh93 `EXIT` trap evaluates in caller scope (for `function name {`). Bash `RETURN` in same scope.|
|`command_not_found_handle` handler function|4.0-alpha||
|official introduction of switchable "compatiblity levels"|4.0-alpha|`compat31` was introduced in a 3.2 version, mainly because of the incompatibilities that were introduced by the changed `=~` operator|
|`[[...]]` and `((...))` conditional commands are subject to the `ERR` trap and `set -e` feature|4.1-alpha||
|ACL support for file status checks|4.1-alpha||
|Assignment to negative array indices|4.3-alpha|ksh93, zsh|
|`declare`/`typeset -n`|4.3-alpha|Support for nameref variable type, a variable referencing another one by name|
|shells started to run process substitutions now run any trap set on `EXIT`|4.3-beta||
|process substitution does not inherit the `v` flag|5.0-alpha||
|`ERR` trap|5.0-alpha|Reports more reliable line numbers|
|Variable assignment|5.0-beta|Assignments preceeding a special builtin that chages variable attributes are not propagated back unless compatiblity mode is 44 or lower|

View File

@ -49,31 +49,31 @@ You can follow the process by using `echo` as a fake interpreter:
#!/bin/echo
We don't need a script body here, as the file will never be interpreted
and executed by \"`echo`\". You can see what the Operating System does,
it calls \"`/bin/echo`\" with the name of the executable file and
and executed by "`echo`". You can see what the Operating System does,
it calls "`/bin/echo`" with the name of the executable file and
following arguments.
$ /home/bash/bin/test testword hello
/home/bash/bin/test testword hello
The same way, with `#!/bin/bash` the shell \"`/bin/bash`\" is called
The same way, with `#!/bin/bash` the shell "`/bin/bash`" is called
with the script filename as an argument. It's the same as executing
\"`/bin/bash /home/bash/bin/test testword hello`\"
"`/bin/bash /home/bash/bin/test testword hello`"
If the interpreter can be specified with arguments and how long it can
be is system-specific (see
[#!-magic](http://www.in-ulm.de/~mascheck/various/shebang/)). When Bash
executes a file with a #!/bin/bash shebang, the shebang itself is
ignored, since the first character is a hashmark \"#\", which indicates
ignored, since the first character is a hashmark "`#`", which indicates
a comment. The shebang is for the operating system, not for the shell.
Programs that don't ignore such lines, may not work as shebang driven
interpreters.
<WRAP center round important 60%> [**Attention:**]{.underline}When the
<WRAP center round important 60%> <u>**Attention:**</u>When the
specified interpreter is unavailable or not executable (permissions),
you usually get a \"`bad interpreter`\" error message., If you get
you usually get a "`bad interpreter`" error message., If you get
nothing and it fails, check the shebang. Older Bash versions will
respond with a \"`no such file or directory`\" error for a nonexistant
respond with a "`no such file or directory`" error for a nonexistant
interpreter specified by the shebang. </WRAP>
**Additional note:** When you specify `#!/bin/sh` as shebang and that's
@ -85,7 +85,7 @@ A common method is to specify a shebang like
#!/usr/bin/env bash
\...which just moves the location of the potential problem to
...which just moves the location of the potential problem to
- the `env` utility must be located in /usr/bin/
- the needed `bash` binary must be located in `PATH`
@ -104,7 +104,7 @@ files*:
- **stdout**: standard output
- **stderr**: standard error output
Usually, they\'re all connected to your terminal, stdin as input file
Usually, they're all connected to your terminal, stdin as input file
(keyboard), stdout and stderr as output files (screen). When calling
such a program, the invoking shell can change these filedescriptor
connections away from the terminal to any other file (see redirection).
@ -179,8 +179,8 @@ else
fi
```
A common decision making command is \"`test`\" or its equivalent
\"`[`\". But note that, when calling test with the name \"`[`\", the
A common decision making command is "`test`" or its equivalent
"`[`". But note that, when calling test with the name "`[`", the
square brackets are not part of the shell syntax, the left bracket
**is** the test command!
@ -194,7 +194,7 @@ fi
Read more about [the test command](../commands/classictest.md)
A common exit code check method uses the \"`||`\" or \"`&&`\" operators.
A common exit code check method uses the "`||`" or "`&&`" operators.
This lets you execute a command based on whether or not the previous
command completed successfully:
@ -203,13 +203,13 @@ grep ^root: /etc/passwd >/dev/null || echo "root was not found - check the pub a
which vi && echo "Your favourite editor is installed."
```
Please, when your script exits on errors, provide a \"FALSE\" exit code,
Please, when your script exits on errors, provide a "`FALSE`" exit code,
so others can check the script execution.
## Comments
In a larger, or complex script, it's wise to comment the code. Comments
can help with debugging or tests. Comments start with the \# character
can help with debugging or tests. Comments start with the `#` character
(hashmark) and continue to the end of the line:
``` bash
@ -226,7 +226,7 @@ All three syntactically correct.
### Block commenting
To temporarily disable complete blocks of code you would normally have
to prefix every line of that block with a \# (hashmark) to make it a
to prefix every line of that block with a `#` (hashmark) to make it a
comment. There's a little trick, using the pseudo command `:` (colon)
and input redirection. The `:` does nothing, it's a pseudo command, so
it does not care about standard input. In the following code example,
@ -254,14 +254,14 @@ redirection (a here-document) - the pseudo command didn't care about
it, effectively, the entire block was ignored.
The here-document-tag was quoted here **to avoid substitutions** in the
\"commented\" text! Check [redirection with
"commented" text! Check [redirection with
here-documents](../syntax/redirection.md#tag_heredoc) for more
## Variable scope
In Bash, the scope of user variables is generally *global*. That means,
it does **not** matter whether a variable is set in the \"main program\"
or in a \"function\", the variable is defined everywhere.
it does **not** matter whether a variable is set in the "main program"
or in a "function", the variable is defined everywhere.
Compare the following *equivalent* code snippets:
@ -280,10 +280,10 @@ echo $myvariable
```
In both cases, the variable `myvariable` is set and accessible from
everywhere in that script, both in functions and in the \"main
program\".
everywhere in that script, both in functions and in the "main
program".
**[Attention:]{.underline}** When you set variables in a child process,
**<u>Attention:</u>** When you set variables in a child process,
for example a *subshell*, they will be set there, but you will **never**
have access to them outside of that subshell. One way to create a
subshell is the pipe. It's all mentioned in a small article about [Bash
@ -359,7 +359,7 @@ export myvariable
```
Remember that the *exported* variable is a **copy**. There is no
provision to \"copy it back to the parent.\" See the article about [Bash
provision to "copy it back to the parent." See the article about [Bash
in the process tree](../scripting/processtree.md)!
[^1]: under specific circumstances, also by the shell itself

View File

@ -16,16 +16,16 @@ but as hints and comments about debugging a Bash script.
## Use a unique name for your script
Do **not** name your script `test`, for example! *Why?* `test` is the
name of a UNIX(r)-command, and [most likely built into your
shell]{.underline} (it's a built-in in Bash) - so you won't be able to
name of a UNIX(r)-command, and <u>most likely built into your
shell</u> (it's a built-in in Bash) - so you won't be able to
run a script with the name `test` in a normal way.
**Don't laugh!** This is a classic mistake :-)
## Read the error messages
Many people come into IRC and ask something like *\"Why does my script
fail? I get an error!\"*. And when you ask them what the error message
Many people come into IRC and ask something like *"Why does my script
fail? I get an error!"*. And when you ask them what the error message
is, they don't even know. Beautiful.
Reading and interpreting error messages is 50% of your job as debugger!
@ -33,9 +33,9 @@ Error messages actually **mean** something. At the very least, they can
give you hints as to where to start debugging. **READ YOUR ERROR
MESSAGES!**
You may ask yourself why is this mentioned as debugging tip? Well, [you
You may ask yourself why is this mentioned as debugging tip? Well, <u>you
would be surprised how many shell users ignore the text of error
messages!]{.underline} When I find some time, I\'ll paste 2 or 3 IRC
messages!</u> When I find some time, I'll paste 2 or 3 IRC
log-snips here, just to show you that annoying fact.
## Use a good editor
@ -85,7 +85,7 @@ There are two useful debug outputs for that task (both are written to
- print commands to be executed to `stderr` as if they were read
from input (script file or keyboard)
- print everything **before** any ([substitution and
expansion](../syntax/expansion/intro.md), \...) is applied
expansion](../syntax/expansion/intro.md), ...) is applied
- `set -x` mode (`set -o xtrace`)
- print everything as if it were executed, after [substitution and
expansion](../syntax/expansion/intro.md) is applied
@ -98,7 +98,7 @@ There are two useful debug outputs for that task (both are written to
configurable file descriptor, rather than sdtout by setting the
[BASH_XTRACEFD](../syntax/shellvars.md#BASH_XTRACEFD) variable.
**[Hint:]{.underline}** These modes can be entered when calling Bash:
**<u>Hint:</u>** These modes can be entered when calling Bash:
- from commandline: `bash -vx ./myscript`
- from shebang (OS dependant): `#!/bin/bash -vx`
@ -116,9 +116,9 @@ That fails. Why? Let's see the `xtrace` output:
+ '[' bar baz = test ']'
And now you see that it's (\"bar\" and \"baz\") recognized as two
And now you see that it's ("bar" and "baz") recognized as two
separate words (which you would have realized if you READ THE ERROR
MESSAGES ;) ). Let's check it\...
MESSAGES ;) ). Let's check it...
# next try
[ "$foo" = test ]
@ -146,7 +146,7 @@ function*:
+(somefile.bash:412): echo 'Hello world'
\...and like this when you trace code *inside a function*:
...and like this when you trace code *inside a function*:
+(somefile.bash:412): myfunc(): echo 'Hello world'
@ -236,14 +236,14 @@ command](../syntax/ccmd/intro.md):
- did you close your `{` with a `}`?
- did you close your `(` with a `)`?
**[Note:]{.underline}** It seems that here-documents (tested on versions
<u>**Note:**</u> It seems that here-documents (tested on versions
`1.14.7`, `2.05b`, `3.1.17` and `4.0`) are correctly terminated when
there is an EOF before the end-of-here-document tag (see
[redirection](../syntax/redirection.md)). The reason is unknown, but it seems
to be deliberate. Bash 4.0 added an extra message for this:
`` warning: here-document at line <N> delimited by end-of-file (wanted `<MARKER>') ``
### Unexpected end of file while looking for matching \...
### Unexpected end of file while looking for matching ...
script.sh: line 50: unexpected EOF while looking for matching `"'
script.sh: line 100: syntax error: unexpected end of file
@ -266,13 +266,13 @@ example for `xtrace` output from above. External commands may display
such an error message though in our example, it was the **internal**
test-command that yielded the error.
### !\": event not found
### !": event not found
$ echo "Hello world!"
bash: !": event not found
This is not an error per se. It happens in interactive shells, when the
C-Shell-styled history expansion (\"`!searchword`\") is enabled. This is
C-Shell-styled history expansion ("`!searchword`") is enabled. This is
the default. Disable it like this:
set +H
@ -317,8 +317,8 @@ CRs are a pain.
Some possible sources of CRs:
- a DOS/Windows text editor
- a UNIX(r) text editor that is \"too smart\" when determining the
file content type (and thinks \"*it's a DOS text file*\")
- a UNIX(r) text editor that is "too smart" when determining the
file content type (and thinks "*it's a DOS text file*")
- a direct copy and paste from certain webpages (some pastebins are
known for this)
@ -343,7 +343,7 @@ Here's what happens because of the `#!/bin/bash^M` in our shebang:
problem.
- the script can't be executed
The error message can vary. If you\'re lucky, you\'ll get:
The error message can vary. If you're lucky, you'll get:
bash: ./testing.sh: /bin/bash^M: bad interpreter: No such file or directory
@ -355,9 +355,10 @@ Why? Because when printed literally, the `^M` makes the cursor go back
to the beginning of the line. The whole error message is *printed*, but
you *see* only part of it!
<note warning> It's easy to imagine the `^M` is bad in other places
too. If you get weird and illogical messages from your script, rule out
the possibility that`^M` is involved. Find and eliminate it! </note>
!!! warning "warning"
It's easy to imagine the `^M` is bad in other places
too. If you get weird and illogical messages from your script, rule out
the possibility that`^M` is involved. Find and eliminate it!
### How can I find and eliminate them?
@ -376,7 +377,8 @@ the possibility that`^M` is involved. Find and eliminate it! </note>
- [the set builtin command](../commands/builtin/set.md) (for `-v` and `-x`)
FIXME
!!! warning "FIXME"
tbd.
- DEBUG trap
- BASH Debugger <http://bashdb.sourceforge.net/>

View File

@ -17,8 +17,8 @@ Here are some typical traps:
### Your perfect Bash script executes with syntax errors
If you write Bash scripts with Bash specific syntax and features, run
them with [Bash]{.underline}, and run them with Bash in [native
mode]{.underline}.
them with <u>Bash</u>, and run them with Bash in <u>native
mode</u>.
**Wrong**:
@ -36,7 +36,7 @@ See also:
- [Bash startup mode: SH mode](../scripting/bashbehaviour.md#sh_mode)
- [Bash run mode: POSIX mode](../scripting/bashbehaviour.md#posix_run_mode)
### Your script named \"test\" doesn't execute
### Your script named "test" doesn't execute
Give it another name. The executable `test` already exists.

View File

@ -21,27 +21,16 @@ e.g. if there is a corresponding POSIX(r)-compatible syntax (see
Some syntax elements have a BASH-specific, and a portable[^1]) pendant.
In these cases the portable syntax should be preferred.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
construct portable equivalent Description Portability
------------------------------------------ --------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -----------------------------------------------
`source\ FILE` `. FILE` include a script file Bourne shell (bash, ksh, POSIX(r), zsh, \...)
`declare`\\ keyword `typeset` keyword define local variables (or variables with special attributes) ksh, zsh, \..., **not POSIX!**
`command\ <<<\ WORD` `command <<MARKER WORD MARKER` a here-string, a special form of the here-document, avoid it in portable scripts! POSIX(r)
`export VAR=VALUE` `VAR=VALUE export VAR` Though POSIX(r) allows it, some shells don't want the assignment and the exporting in one command POSIX(r), zsh, ksh, \...
`(( MATH ))` `: $(( MATH ))` POSIX(r) does't define an arithmetic compund command, many shells don't know it. Using the pseudo-command `:` and the arithmetic expansion `$(( ))` is a kind of workaround here. **Attention:** Not all shell support assignment like `$(( a = 1 + 1 ))`! Also see below for a probably more portable solution. all POSIX(r) compatible shells
`[[\ EXPRESSION\ ]]` `[ EXPRESSION ]`\ The Bashish test keyword is reserved by POSIX(r), but not defined. Use the old fashioned way with the `test` command. See [the classic test command](../commands/classictest.md) POSIX(r) and others
or\
`test EXPRESSION`
`COMMAND\ <\ <(\ ...INPUTCOMMANDS...\ )` `INPUTCOMMANDS\ >\ TEMPFILE COMMAND\ <\ TEMPFILE` Process substitution (here used with redirection); use the old fashioned way (tempfiles) POSIX(r) and others
`((echo X);(echo Y))` `( (echo X); (echo Y) )` Nested subshells (separate the inner `()` from the outer `()` by spaces, to not confuse the shell regarding arithmetic control operators) POSIX(r) and others
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|construct|portable equivalent|Description|Portability|
|---------|-------------------|-----------|-----------|
|`source FILE`|`. FILE`|include a script file|Bourne shell (bash, ksh, POSIX(r), zsh, …)|
|`declare` keyword|`typeset` keyword|define local variables (or variables with special attributes)|ksh, zsh, …, **not POSIX!**|
|`command <<< WORD`|`command <<MARKER`\n`WORD`\n`MARKER`|a here-string, a special form of the here-document, avoid it in portable scripts!|POSIX(r)|
|`export VAR=VALUE`|`VAR=VALUE`\n`export VAR`|Though POSIX(r) allows it, some shells don't want the assignment and the exporting in one command|POSIX(r), zsh, ksh, …|
|`(( MATH ))`|`: $(( MATH ))`|POSIX(r) does't define an arithmetic compund command, many shells don't know it. Using the pseudo-command `:` and the arithmetic expansion `$(( ))` is a kind of workaround here. **Attention:** Not all shell support assignment like `$(( a = 1 + 1 ))`! Also see below for a probably more portable solution.|all POSIX(r) compatible shells|
|`[[ EXPRESSION ]]`|`[ EXPRESSION ]`\nor\n`test EXPRESSION`|The Bashish test keyword is reserved by POSIX(r), but not defined. Use the old fashioned way with the `test` command. See [[web/20230315170826/https://wiki.bash-hackers.org/commands/classictest]]|POSIX(r) and others|
|`COMMAND < <( …INPUTCOMMANDS… )`|`INPUTCOMMANDS > TEMPFILE`\n`COMMAND < TEMPFILE`|Process substitution (here used with redirection); use the old fashioned way (tempfiles)|POSIX(r) and others|
|`((echo X);(echo Y))`|`( (echo X); (echo Y) )`|Nested subshells (separate the inner `()` from the outer `()` by spaces, to not confuse the shell regarding arithmetic control operators)|POSIX(r) and others|
## Portability rationale
@ -51,8 +40,9 @@ will be!) and it's not very detailed (e.g. you won't find information
about how which shell technically forks off which subshell). It's just
an assorted small set of portability guidelines. *-Thebonsai*
FIXME UNIX shell gurus out there, please be patient with a newbie like
me and give comments and hints instead of flames.
!!! warning "FIXME"
UNIX shell gurus out there, please be patient with a newbie like me
and give comments and hints instead of flames.
### Environment (exported) variables
@ -100,7 +90,7 @@ Why? (list of known behaviours)
- may or may not automatically interpret backslash escpape codes in
the strings
- may or may not automatically interpret switches (like `-n`)
- may or may not ignore \"end of options\" tag (`--`)
- may or may not ignore "end of options" tag (`--`)
- `echo -n` and `echo -e` are neither portable nor standard (**even
within the same shell**, depending on the version or environment
variables or the build options, especially KSH93 and Bash)
@ -113,7 +103,7 @@ existance of [the `printf` command](../commands/builtin/printf.md).
- `${var:x:x}` is KSH93/Bash specific
- `${var/../..}` and `${var//../..}` are KSH93/Bash specific
- `var=$*` and `var=$@` are not handled the same in all shells if the
first char of IFS is not \" \" (space). `var="$*"` should work
first char of IFS is not " " (space). `var="$*"` should work
(except the Bourne shell always joins the expansions with space)
### Special variables
@ -130,11 +120,11 @@ of your script:
#### RANDOM
[RANDOM](../syntax/shellvars.md#RANDOM) is Bash/KSH/ZSH specific variable
that will give you a random number up to 32767 (2\^15-1). Among many
that will give you a random number up to 32767 (2^15-1). Among many
other available external options, you can use awk to generate a random
number. There are multiple implementations of awk and which version your
system uses will depend. Most modern systems will call \'gawk\' (i.e.
GNU awk) or \'nawk\'. \'oawk\' (i.e. Original/Old awk) does not have the
system uses will depend. Most modern systems will call 'gawk' (i.e.
GNU awk) or 'nawk'. 'oawk' (i.e. Original/Old awk) does not have the
rand() or srand() functions, so is best avoided.
# 'gawk' can produce random numbers using srand(). In this example, 10 integers between 1 and 500:
@ -143,7 +133,7 @@ rand() or srand() functions, so is best avoided.
# 'nawk' and 'mawk' does the same, but needs a seed to be provided for its rand() function. In this example we use $(date)
randpm=$(mawk -v min=1 -v max=500 -v nNum=10 -v seed="$(date +%Y%M%d%H%M%S)" 'BEGIN { srand(seed); for (i = 0; i < nNum; ++i) {print int(min + rand() * (max - min)} }')
*Yes, I\'m not an `awk` expert, so please correct it, rather than
*Yes, I'm not an `awk` expert, so please correct it, rather than
complaining about possible stupid code!*
# Well, seeing how this //is// BASH-hackers.org I kinda missed the bash way of doing the above ;-)
@ -162,7 +152,7 @@ Find another method.
The [PATH](../syntax/shellvars.md#PATH) variable is a colon-delimited list of
directory names, so it's basically possible to run a loop and check
every `PATH` component for the command you\'re looking for and for
every `PATH` component for the command you're looking for and for
executability.
However, this method doesn't look nice. There are other ways of doing
@ -207,6 +197,6 @@ accessible by `PATH`:
echo "sed is available"
fi
[^1]: \"portable\" doesn't necessarily mean it's POSIX, it can also
mean it's \"widely used and accepted\", and thus maybe more
[^1]: "portable" doesn't necessarily mean it's POSIX, it can also
mean it's "widely used and accepted", and thus maybe more
portable than POSIX(r

View File

@ -15,6 +15,8 @@ obsolete by some measure. A thorough discussion of the rationale is
beyond the scope of this page. See the [portability
page](../scripting/nonportable.md) for a discussion on portability issues.
## Tolerated but few ligitimate uses
This first table lists syntax that is tolerated by Bash but has few if
any legitimate uses. These features exist mostly for Bourne, csh, or
some other backward compatibility with obsolete shells, or were
@ -24,13 +26,16 @@ everyone except maybe code golfers. New scripts should never use them.
None of the items on this list are specified by the most current version
of POSIX, and some may be incompatible with POSIX.
Syntax Replacement Description
---------------------------------- --------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
`&>FILE` and `>&FILE` `>FILE 2>&1` This redirection syntax is short for `>FILE 2>&1` and originates in the C Shell. The latter form is especially uncommon and should never be used, and the explicit form using separate redirections is preferred over both. These shortcuts contribute to confusion about the copy descriptor because the syntax is unclear. They also introduce parsing ambiguity, and conflict with POSIX. Shells without this feature treat `cmd1 &>file cmd2` as: \"background `cmd1` and then execute `cmd2` with its stdout redirected to `file`\", which is the correct interpretation of this expression. See: [redirection](../syntax/redirection.md) \`\$ { bash; dash </dev/fd/0; } <<<\'echo foo>/dev/null&>/dev/fd/2 echo bar\' foo echo bar bar\`
`$[EXPRESSION]` `$((EXPRESSION))` This undocumented syntax is completely replaced by the POSIX-conforming arithmetic expansion `$((EXPRESSION))`. It is unimplemented almost everywhere except Bash and Zsh. See [arithmetic expansion](../syntax/expansion/arith.md). [Some discussion](http://lists.gnu.org/archive/html/bug-bash/2012-04/msg00034.html).
`COMMAND\ |&\ COMMAND` `COMMAND 2>&1 | COMMAND` This is an alternate pipeline operator derived from Zsh. Officially, it is not considered deprecated by Bash, but I highly discourage it. It conflicts with the list operator used for [coprocess](../syntax/keywords/coproc.md) creation in most Korn shells. It also has confusing behavior. The stdout is redirected first like an ordinary pipe, while the stderr is actually redirected last -- after other redirects preceding the pipe operator. Overall, it's pointless syntax bloat. Use an explicit redirect instead.
`function\ NAME()\ COMPOUND-CMD` `NAME()\ COMPOUND-CMD` or `function\ NAME\ {\ CMDS;\ }` This is an amalgamation between the Korn and POSIX style function definitions - using both the `function` keyword and parentheses. It has no useful purpose and no historical basis or reason to exist. It is not specified by POSIX. It is accepted by Bash, mksh, zsh, and perhaps some other Korn shells, where it is treated as identical to the POSIX-style function. It is not accepted by AT&T ksh. It should never be used. See the next table for the `function` keyword. Bash doesn't have this feature documented as expressly deprecated.
`for x; { ...;}` `do`, `done`, `in`, `esac`, etc. This undocumented syntax replaces the `do` and `done` reserved words with braces. Many Korn shells support various permutations on this syntax for certain compound commands like `for`, `case`, and `while`. Which ones and certain details like whether a newline or semicolon are required vary. Only `for` works in Bash. Needless to say, don't use it.
|Syntax|Replacement|Description|
|--|--|--|
|`&>FILE` and `>&FILE`|`>FILE 2>&1`|This redirection syntax is short for `>FILE 2>&1` and originates in the C Shell. The latter form is especially uncommon and should never be used, and the explicit form using separate redirections is preferred over both. These shortcuts contribute to confusion about the copy descriptor because the syntax is unclear. They also introduce parsing ambiguity, and conflict with POSIX. Shells without this feature treat `cmd1 &>file cmd2` as: "background `cmd1` and then execute `cmd2` with its stdout redirected to `file`", which is the correct interpretation of this expression. See: [redirection](../syntax/redirection.md) <pre>$ { bash; dash </dev/fd/0; } <<<'echo foo>/dev/null&>/dev/fd/2 echo bar'<br>foo echo bar<br>bar</pre>|
|`$[EXPRESSION]`|`$((EXPRESSION))`|This undocumented syntax is completely replaced by the POSIX-conforming arithmetic expansion `$((EXPRESSION))`. It is unimplemented almost everywhere except Bash and Zsh. See [arithmetic expansion](../syntax/expansion/arith.md). [Some discussion](http://lists.gnu.org/archive/html/bug-bash/2012-04/msg00034.html).|
|`COMMAND|& COMMAND`|`COMMAND 2>&1| COMMAND`|This is an alternate pipeline operator derived from Zsh. Officially, it is not considered deprecated by Bash, but I highly discourage it. It conflicts with the list operator used for [coprocess](../syntax/keywords/coproc.md) creation in most Korn shells. It also has confusing behavior. The stdout is redirected first like an ordinary pipe, while the stderr is actually redirected last after other redirects preceding the pipe operator. Overall, it's pointless syntax bloat. Use an explicit redirect instead.|
|`function NAME() COMPOUND-CMD`|`NAME() COMPOUND-CMD` or `function NAME { CMDS; }`|This is an amalgamation between the Korn and POSIX style function definitions - using both the `function` keyword and parentheses. It has no useful purpose and no historical basis or reason to exist. It is not specified by POSIX. It is accepted by Bash, mksh, zsh, and perhaps some other Korn shells, where it is treated as identical to the POSIX-style function. It is not accepted by AT&T ksh. It should never be used. See the next table for the `function` keyword. Bash doesn't have this feature documented as expressly deprecated.|
|`for x; { ...;}`|`do`, `done`, `in`, `esac`, etc.|This undocumented syntax replaces the `do` and `done` reserved words with braces. Many Korn shells support various permutations on this syntax for certain compound commands like `for`, `case`, and `while`. Which ones and certain details like whether a newline or semicolon are required vary. Only `for` works in Bash. Needless to say, don't use it.|
## Syntax superseded by superior alternatives
This table lists syntax that is specified by POSIX (unless otherwise
specified below), but has been superseded by superior alternatives
@ -39,43 +44,33 @@ reasons such as encouraging bad practices or dangerous code. Those that
are specified by POSIX may be badly designed and unchangeable for
historical reasons.
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Syntax Replacement Description
----------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------- -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Unquoted expansions, [wordsplit](../syntax/expansion/wordsplit.md), and [globs](../syntax/expansion/globs.md) [Proper quoting](http://mywiki.wooledge.org/Quotes), Ksh/Bash-style [arrays](../syntax/arrays.md), The \"\$@\" expansion, [read](../commands/builtin/read.md) *Quoting errors* are a broad category of common mistakes brought about by a few unintuitive features carried over from the Bourne shell due to complaints of broken scripts and changes in previously documented behavior. Most of the important expansions are performed at the same time from left to right. However, a few expansions, most notably word-splitting and globbing, and in shells other than Bash, [brace expansion](../syntax/expansion/brace.md), are performed **on the results of previous expansions, by default, unless they are quoted.** This means that the act of expanding an unquoted variable in an ordinary argument context, depending on the value of the variable, can yield different results depending on possibly uncontrolled side-effects like the value of `IFS`, and the names of files in the current working directory. You can't get globbing without word-splitting, or vice versa (without `set -f`). [You can't store a command or character-delimited list in a variable and safely evaluate it with unquoted expansion](http://mywiki.wooledge.org/BashFAQ/050). If possible, always choose a shell that supports Korn shell arrays such as Bash. They are a vital but non-standard feature for writing clean, safe scripts. Well-written scripts don't use word-splitting. A few exceptions are listed on the [word splitting page](../syntax/expansion/wordsplit.md). A significant proportion of the issues on the famous [Pitfalls list](http://mywiki.wooledge.org/BashPitfalls) fall under this category. See also: *[Don't read lines with for!](http://mywiki.wooledge.org/DontReadLinesWithFor)*
|Syntax|Replacement|Description|
|------|-----------|-----------|
|Unquoted expansions, [wordsplitting](../syntax/expansion/wordsplit.md), and [Pathname expansion (globbing)](../syntax/expansion/globs.md)|[Proper quoting](http://mywiki.wooledge.org/Quotes), Ksh/Bash-style [arrays](../syntax/arrays.md), The "$@" expansion, [the read builtin command](../commands/builtin/read.md)|*Quoting errors* are a broad category of common mistakes brought about by a few unintuitive features carried over from the Bourne shell due to complaints of broken scripts and changes in previously documented behavior. Most of the important expansions are performed at the same time from left to right. However, a few expansions, most notably word-splitting and globbing, and in shells other than Bash, [brace expansion](../syntax/expansion/brace.md), are performed **on the results of previous expansions, by default, unless they are quoted.** This means that the act of expanding an unquoted variable in an ordinary argument context, depending on the value of the variable, can yield different results depending on possibly uncontrolled side-effects like the value of `IFS`, and the names of files in the current working directory. You can't get globbing without word-splitting, or vice versa (without `set -f`). [You can't store a command or character-delimited list in a variable and safely evaluate it with unquoted expansion](http://mywiki.wooledge.org/BashFAQ/050). If possible, always choose a shell that supports Korn shell arrays such as Bash. They are a vital but non-standard feature for writing clean, safe scripts. Well-written scripts don't use word-splitting. A few exceptions are listed on the [word splitting page](../syntax/expansion/wordsplit.md). A significant proportion of the issues on the famous [Pitfalls list](http://mywiki.wooledge.org/BashPitfalls) fall under this category. See also: *[Don't read lines with for!](http://mywiki.wooledge.org/DontReadLinesWithFor)*|
|``COMMANDS``|`$(COMMANDS)`|his is the older Bourne-compatible form of the [command substitution](../syntax/expansion/cmdsubst.md). Both the `` `COMMANDS` `` and `$(COMMANDS)` syntaxes are specified by POSIX, but the latter is [greatly]{.underline} preferred, though the former is unfortunately still very prevalent in scripts. New-style command substitutions are widely implemented by every modern shell (and then some). The only reason for using backticks is for compatibility with a real Bourne shell (like Heirloom). Backtick command substitutions require special escaping when nested, and examples found in the wild are improperly quoted more often than not. See: *[Why is $(...) preferred over `...` (backticks)?](http://mywiki.wooledge.org/BashFAQ/082)*.|
|`[ EXPRESSION ]` and `test EXPRESSION`|`[[ EXPRESSION ]]`|`test` and `[` are the Bourne/POSIX commands for evaluating test expressions (they are almost identical, and `[` is somewhat more common). The expressions consist of regular arguments, unlike the Ksh/Bash `[[` command. While the issue is analogous to `let` vs `((`, the advantages of `[[` vs `[` are even more important because the arguments/expansions aren't just concatenated into one expression. With the classic `[` command, the number of arguments is significant. If at all possible, use the [conditional expression](../syntax/ccmd/conditional_expression.md) ("new test command") `[[ EXPRESSION ]]`. Unless there is a need for POSIX compatibility, there are only a few reasons to use `[`. `[[` is one of the most portable and consistent non-POSIX ksh extensions available. See: [conditional_expression](../syntax/ccmd/conditional_expression.md) and *[What is the difference between test, \[ and \[\[ ?](http://mywiki.wooledge.org/BashFAQ/031)*|
|`set -e`, `set -o errexit` and the `ERR` trap|proper control flow and error handling|`set -e` causes untested non-zero exit statuses to be fatal. It is a debugging feature intended for use only during development and should not be used in production code, especially init scripts and other high-availability scripts. Do not be tempted to think of this as "error handling"; it's not, it's just a way to find the place you've *forgotten* to put error handling.<br>Think of it as akin to `use strict` in Perl or `throws` in C++: tough love that makes you write better code. Many guides recommend avoiding it entirely because of the apparently-complex rules for when non-zero statuses cause the script to abort. Conversely, large software projects with experienced coders may recommend or even mandate its use.<br>Because it provides no notification of the location of the error, it's more useful combined with `set -x` or the `DEBUG` trap and other Bash debug features, and both flags are normally better set on the command line rather than within the script itself.<br>Most of this also applies to the `ERR` trap, though I've seen it used in a few places in shells that lack `pipefail` or `PIPESTATUS`. The `ERR` trap is not POSIX, but `set -e` is. `failglob` is another Bash feature that falls into this category (mainly useful for debugging).<br>**The `set -e` feature generates more questions and false bug reports on the Bash mailing list than all other features combined!** Please do not rely on `set -e` for logic in scripts. If you still refuse to take this advice, make sure you understand **exactly** how it works. See: *[Why doesn't set -e (or set -o errexit, or trap ERR) do what I expected?](http://mywiki.wooledge.org/BashFAQ/105)* and <http://www.fvue.nl/wiki/Bash:_Error_handling>|
|`set -u` or `set -o nounset`|Proper control flow and error handling|`set -u` causes attempts to expand unset variables or parameters as fatal errors. Like `set -e`, it bypasses control flow and exits immediately from the current shell environment. Like non-zero statuses, unset variables are a normal part of most non-trivial shell scripts. Living with `set -u` requires hacks like `${1+"$1"}` for each expansion that might possibly be unset. Only very current shells guarantee that expanding `@` or `*` won't trigger an error when no parameters are set (<http://austingroupbugs.net/view.php?id=155>, <http://www.in-ulm.de/~mascheck/various/bourne_args/>). Apparently some find it useful for debugging. See [How do I determine whether a variable is already defined? Or a function?](http://mywiki.wooledge.org/BashFAQ/083) for how to properly test for defined variables. Don't use `set -u`.|
|`${var?msg}` or `${var:?msg}`|Proper control flow and error handling|Like `set -u`, this expansion causes a fatal error which immediately exits the current shell environment if the given parameter is unset or is null. It prints the error message given, to the right of the operator. If a value is expected and you'd like to create an assertion or cause errors, it's better to test for undefined variables using one of [these techniques](http://mywiki.wooledge.org/BashFAQ/083) and handle the error manually, or call a `die` function. This expansion is defined by POSIX. It's better than `set -u`, because it's explicit, but not by much. It also allows you to accidentally construct hilariously deceptive error messages: <pre>bash -c 'f() { definitely_not_printf "${printf:?"$1" - No such option}"; }; f -v'<br>bash: printf: -v - No such option</pre>|
`` `COMMANDS` `` `$(COMMANDS)` This is the older Bourne-compatible form of the [command substitution](../syntax/expansion/cmdsubst.md). Both the `` `COMMANDS` `` and `$(COMMANDS)` syntaxes are specified by POSIX, but the latter is [greatly]{.underline} preferred, though the former is unfortunately still very prevalent in scripts. New-style command substitutions are widely implemented by every modern shell (and then some). The only reason for using backticks is for compatibility with a real Bourne shell (like Heirloom). Backtick command substitutions require special escaping when nested, and examples found in the wild are improperly quoted more often than not. See: *[Why is \$(\...) preferred over \`\...\` (backticks)?](http://mywiki.wooledge.org/BashFAQ/082)*.
`[\ EXPRESSION\ ]`\\ and\\ `test\ EXPRESSION` `[[\ EXPRESSION\ ]]` `test` and `[` are the Bourne/POSIX commands for evaluating test expressions (they are almost identical, and `[` is somewhat more common). The expressions consist of regular arguments, unlike the Ksh/Bash `[[` command. While the issue is analogous to `let` vs `((`, the advantages of `[[` vs `[` are even more important because the arguments/expansions aren't just concatenated into one expression. With the classic `[` command, the number of arguments is significant. If at all possible, use the [conditional expression](../syntax/ccmd/conditional_expression.md) (\"new test command\") `[[ EXPRESSION ]]`. Unless there is a need for POSIX compatibility, there are only a few reasons to use `[`. `[[` is one of the most portable and consistent non-POSIX ksh extensions available. See: [conditional_expression](../syntax/ccmd/conditional_expression.md) and *[What is the difference between test, \[ and \[\[ ?](http://mywiki.wooledge.org/BashFAQ/031)*
`set -e`, `set -o errexit`\ proper control flow and error handling `set -e` causes untested non-zero exit statuses to be fatal. It is a debugging feature intended for use only during development and should not be used in production code, especially init scripts and other high-availability scripts. Do not be tempted to think of this as \"error handling\"; it's not, it's just a way to find the place you\'ve *forgotten* to put error handling.\
and the `ERR` trap Think of it as akin to `use strict` in Perl or `throws` in C++: tough love that makes you write better code. Many guides recommend avoiding it entirely because of the apparently-complex rules for when non-zero statuses cause the script to abort. Conversely, large software projects with experienced coders may recommend or even mandate its use.\
Because it provides no notification of the location of the error, it's more useful combined with `set -x` or the `DEBUG` trap and other Bash debug features, and both flags are normally better set on the command line rather than within the script itself.\
Most of this also applies to the `ERR` trap, though I\'ve seen it used in a few places in shells that lack `pipefail` or `PIPESTATUS`. The `ERR` trap is not POSIX, but `set -e` is. `failglob` is another Bash feature that falls into this category (mainly useful for debugging).\
**The `set -e` feature generates more questions and false bug reports on the Bash mailing list than all other features combined!** Please do not rely on `set -e` for logic in scripts. If you still refuse to take this advice, make sure you understand **exactly** how it works. See: *[Why doesn't set -e (or set -o errexit, or trap ERR) do what I expected?](http://mywiki.wooledge.org/BashFAQ/105)* and <http://www.fvue.nl/wiki/Bash:_Error_handling>
`set -u` or `set -o nounset` Proper control flow and error handling `set -u` causes attempts to expand unset variables or parameters as fatal errors. Like `set -e`, it bypasses control flow and exits immediately from the current shell environment. Like non-zero statuses, unset variables are a normal part of most non-trivial shell scripts. Living with `set -u` requires hacks like `${1+"$1"}` for each expansion that might possibly be unset. Only very current shells guarantee that expanding `@` or `*` won't trigger an error when no parameters are set (<http://austingroupbugs.net/view.php?id=155>, <http://www.in-ulm.de/~mascheck/various/bourne_args/>). Apparently some find it useful for debugging. See *[How do I determine whether a variable is already defined? Or a function?](http://mywiki.wooledge.org/BashFAQ/083)* for how to properly test for defined variables. Don't use `set -u`.
`${var?msg}` or `${var:?msg}` Proper control flow and error handling Like `set -u`, this expansion causes a fatal error which immediately exits the current shell environment if the given parameter is unset or is null. It prints the error message given, to the right of the operator. If a value is expected and you\'d like to create an assertion or cause errors, it's better to test for undefined variables using one of [these techniques](http://mywiki.wooledge.org/BashFAQ/083) and handle the error manually, or call a `die` function. This expansion is defined by POSIX. It's better than `set -u`, because it's explicit, but not by much. It also allows you to accidentally construct hilariously deceptive error messages: `bash -c 'f() { definitely_not_printf "${printf:?"$1" - No such option}"; }; f -v'
bash: printf: -v - No such option`
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
# Frequently misued
This table lists features that are used only if you have a specific
reason to prefer it over another alternative. These have some legitimate
uses if you know what you\'re doing, such as for those with specific
uses if you know what you're doing, such as for those with specific
portability requirements, or in order to make use of some subtle
behavioral differences. These are frequently (mis)used for no reason.
Writing portable scripts that go outside of POSIX features requires
knowing how to account for many (often undocumented) differences across
many shells. If you do happen to know what you\'re doing, don't be too
many shells. If you do happen to know what you're doing, don't be too
surprised if you run across someone telling you not to use these.
Syntax Replacement Description
------------------------------- --------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
`function\ NAME\ {\ CMDS;\ }` `NAME()\ COMPOUND-CMD` This is the ksh form of function definition created to extend the Bourne and POSIX form with modified behaviors and additional features like local variables. The idea was for new-style functions to be analogous to regular builtins with their own environment and scope, while POSIX-style functions are more like special builtins. `function` is supported by almost every ksh-derived shell including Bash and Zsh, but isn't specified by POSIX. Bash treats all function styles the same, but this is unusual. `function` has some preferable characteristics in many ksh variants, making it more portable for scripts that use non-POSIX extensions by some measures. If you\'re going to use the `function` keyword, it implies that you\'re either targeting Ksh specifically, or that you have detailed knowledge of how to compensate for differences across shells. It should always be used consistently with `typeset`, but never used with `declare` or `local`. Also in ksh93, the braces are not a [command group](../syntax/ccmd/grouping_plain.md), but a required part of the syntax (unlike Bash and others). See [shell function definitions](../syntax/basicgrammar.md#shell_function_definitions)
`typeset` `declare`, `local`, `export`, `readonly` This is closely related to the above, and should often be used together. `typeset` exists primarily for `ksh` compatibility, but is marked as \"deprecated\" in Bash (though I don't entirely agree with this). This makes some sense, because future compatibility can't be guaranteed, and any compatibility at all, requires understanding the non-POSIX features of other shells and their differences. Using `declare` instead of `typeset` emphasizes your intention to be \"Bash-only\", and definitely breaks everywhere else (except possibly zsh if you\'re lucky). The issue is further complicated by Dash and the [Debian policy](http://www.debian.org/doc/debian-policy/ch-files.html#s-scripts) requirement for a `local` builtin, which is itself not entirely compatible with Bash and other shells.
\'\'let \'EXPR\' \'\' `((EXPR))` or `[\ $((EXPR))\ -ne\ 0 ]` `let` is the \"simple command\" variant of arithmetic evaluation command, which takes regular arguments. Both `let` and `((expr))` were present in ksh88, and everything that supports one should support the other. Neither are POSIX. The compound variant is preferable because it doesn't take regular arguments for [wordsplitting](../syntax/expansion/wordsplit.md) and [globbing](../syntax/expansion/globs.md), which makes it safer and clearer. It is also usually faster, especially in Bash, where compound commands are typically significantly faster. Some of the (few) reasons for using `let` are detailed on the [let](../commands/builtin/let.md) page. See [arithmetic evaluation compound command](../syntax/ccmd/arithmetic_eval.md)
`eval` Depends. Often code can be restructured to use better alternatives. `eval` is thrown in here for good measure, as sadly it is so often misused that any use of `eval` (even the rare clever one) is immediately dismissed as wrong by experts, and among the most immediate solutions abused by beginners. In reality, there are correct ways to use `eval`, and even cases in which it's necessary, even in sophisticated shells like Bash and Ksh. `eval` is unusual in that it is less frequently appropriate in more feature-rich shells than in more minimal shells like Dash, where it is used to compensate for more limitations. If you find yourself needing `eval` too frequently, it might be a sign that you\'re either better off using a different language entirely, or trying to borrow an idiom from some other paradigm that isn't well suited to the shell language. By the same token, there are some cases in which working too hard to avoid `eval` ends up adding a lot of complexity and sacrificing all portability. Don't substitute a clever `eval` for something that's a bit \"too clever\", just to avoid the `eval`, yet, take reasonable measures to avoid it where it is sensible to do so. See: [eval](../commands/builtin/eval.md) and [Eval command and security issues](http://mywiki.wooledge.org/BashFAQ/048).
|Syntax|Replacement|Description|
|--|--|--|
|`function NAME { CMDS; }`|`NAME() COMPOUND-CMD`|This is the ksh form of function definition created to extend the Bourne and POSIX form with modified behaviors and additional features like local variables. The idea was for new-style functions to be analogous to regular builtins with their own environment and scope, while POSIX-style functions are more like special builtins. `function` is supported by almost every ksh-derived shell including Bash and Zsh, but isn't specified by POSIX. Bash treats all function styles the same, but this is unusual. `function` has some preferable characteristics in many ksh variants, making it more portable for scripts that use non-POSIX extensions by some measures. If you're going to use the `function` keyword, it implies that you're either targeting Ksh specifically, or that you have detailed knowledge of how to compensate for differences across shells. It should always be used consistently with `typeset`, but never used with `declare` or `local`. Also in ksh93, the braces are not a [command group](../syntax/ccmd/grouping_plain), but a required part of the syntax (unlike Bash and others). See [shell function definitions](../syntax/basicgrammar#shell_function_definitions)|
|`typeset`|`declare`, `local`, `export`, `readonly`|This is closely related to the above, and should often be used together. `typeset` exists primarily for `ksh` compatibility, but is marked as "deprecated" in Bash (though I don't entirely agree with this). This makes some sense, because future compatibility can't be guaranteed, and any compatibility at all, requires understanding the non-POSIX features of other shells and their differences. Using `declare` instead of `typeset` emphasizes your intention to be "Bash-only", and definitely breaks everywhere else (except possibly zsh if you're lucky). The issue is further complicated by Dash and the [Debian policy](http://www.debian.org/doc/debian-policy/ch-files.html#s-scripts) requirement for a `local` builtin, which is itself not entirely compatible with Bash and other shells.|
|`let 'EXPR' `|`((EXPR))` or `[ $((EXPR)) -ne 0 ]`|`let` is the "simple command" variant of arithmetic evaluation command, which takes regular arguments. Both `let` and `((expr))` were present in ksh88, and everything that supports one should support the other. Neither are POSIX. The compound variant is preferable because it doesn't take regular arguments for [wordsplitting](../syntax/expansion/wordsplit) and [globbing](../syntax/expansion/globs), which makes it safer and clearer. It is also usually faster, especially in Bash, where compound commands are typically significantly faster. Some of the (few) reasons for using `let` are detailed on the [let](../commands/builtin/let) page. See [arithmetic evaluation compound command](../syntax/ccmd/arithmetic_eval)|
|`eval`|Depends. Often code can be restructured to use better alternatives.|`eval` is thrown in here for good measure, as sadly it is so often misused that any use of `eval` (even the rare clever one) is immediately dismissed as wrong by experts, and among the most immediate solutions abused by beginners. In reality, there are correct ways to use `eval`, and even cases in which it's necessary, even in sophisticated shells like Bash and Ksh. `eval` is unusual in that it is less frequently appropriate in more feature-rich shells than in more minimal shells like Dash, where it is used to compensate for more limitations. If you find yourself needing `eval` too frequently, it might be a sign that you're either better off using a different language entirely, or trying to borrow an idiom from some other paradigm that isn't well suited to the shell language. By the same token, there are some cases in which working too hard to avoid `eval` ends up adding a lot of complexity and sacrificing all portability. Don't substitute a clever `eval` for something that's a bit "too clever", just to avoid the `eval`, yet, take reasonable measures to avoid it where it is sensible to do so. See: [The eval builtin command](../commands/builtin/eval) and [Eval command and security issues](http://mywiki.wooledge.org/BashFAQ/048 "http://mywiki.wooledge.org/BashFAQ/048").|
## See also

View File

@ -17,15 +17,15 @@ The day will come when you want to give arguments to your scripts. These
arguments are known as **positional parameters**. Some relevant special
parameters are described below:
Parameter(s) Description
------------------ ------------------------------------------------------------------------------------------------------------------------------------
`$0` the first positional parameter, equivalent to `argv[0]` in C, see [the first argument](../scripting/posparams.md#the_first_argument)
`$FUNCNAME` the function name ([**attention**]{.underline}: inside a function, `$0` is still the `$0` of the shell, **not** the function name)
`$1 ... $9` the argument list elements from 1 to 9
`${10} ... ${N}` the argument list elements beyond 9 (note the [parameter expansion](../syntax/pe.md) syntax!)
`$*` all positional parameters except `$0`, see [mass usage](../scripting/posparams.md#mass_usage)
`$@` all positional parameters except `$0`, see [mass usage](../scripting/posparams.md#mass_usage)
`$#` the number of arguments, not counting `$0`
|Parameter(s)|Description|
|------------|-----------|
|`$0`|the first positional parameter, equivalent to `argv[0]` in C, see [the first argument](../scripting/posparams.md#the_first_argument)|
|`$FUNCNAME`|the function name (<u>**attention**</u>: inside a function, `$0` is still the `$0` of the shell, **not** the function name)|
|`$1 ... $9`|the argument list elements from 1 to 9|
|`${10} ... ${N}`|the argument list elements beyond 9 (note the [parameter expansion](../syntax/pe.md) syntax!)|
|`$*`|all positional parameters except `$0`, see [mass usage](../scripting/posparams.md#mass_usage)|
|`$@`|all positional parameters except `$0`, see [mass usage](../scripting/posparams.md#mass_usage)|
|`$#`|the number of arguments, not counting `$0`|
These positional parameters reflect exactly what was given to the script
when it was called.
@ -33,8 +33,7 @@ when it was called.
Option-switch parsing (e.g. `-h` for displaying help) is not performed
at this point.
See also [the dictionary entry for
\"parameter\"](../dict/parameter.md).
See also [the dictionary entry for "parameter"](../dict/parameter.md).
## The first argument
@ -42,13 +41,13 @@ The very first argument you can access is referenced as `$0`. It is
usually set to the script's name exactly as called, and it's set on
shell initialization:
[Testscript]{.underline} - it just echos `$0`:
<u>Testscript</u> - it just echos `$0`:
#!/bin/bash
echo "$0"
You see, `$0` is always set to the name the script is called with (`>`
is the prompt\...):
is the prompt...):
> ./testscript
./testscript
@ -79,7 +78,7 @@ values:
- `$1` will be discarded
- `$2` will become `$1`
- `$3` will become `$2`
- \...
- ...
- in general: `$N` will become `$N-1`
The command can take a number as argument: Number of positions to shift.
@ -139,7 +138,7 @@ a given wordlist. The loop uses the positional parameters as a wordlist:
echo "$arg"
done
[Advantage:]{.underline} The positional parameters will be preserved
<u>Advantage:</u> The positional parameters will be preserved
------------------------------------------------------------------------
@ -172,7 +171,7 @@ There is a [small tutorial dedicated to
### All Positional Parameters
Sometimes it's necessary to just \"relay\" or \"pass\" given arguments
Sometimes it's necessary to just "relay" or "pass" given arguments
to another program. It's very inefficient to do that in one of these
loops, as you will destroy integrity, most likely (spaces!).
@ -180,27 +179,27 @@ The shell developers created `$*` and `$@` for this purpose.
As overview:
Syntax Effective result
-------- -----------------------------
`$*` `$1 $2 $3 ... ${N}`
`$@` `$1 $2 $3 ... ${N}`
`"$*"` `"$1c$2c$3c...c${N}"`
`"$@"` `"$1" "$2" "$3" ... "${N}"`
|Syntax|Effective result|
|-------|----------------------------|
|`$*`|`$1 $2 $3 ... ${N}`|
|`$@`|`$1 $2 $3 ... ${N}`|
|`"$*"`|`"$1c$2c$3c...c${N}"`|
|`"$@"`|`"$1" "$2" "$3" ... "${N}"`|
Without being quoted (double quotes), both have the same effect: All
positional parameters from `$1` to the last one used are expanded
without any special handling.
When the `$*` special parameter is double quoted, it expands to the
equivalent of: `"$1c$2c$3c$4c........$N"`, where \'c\' is the first
equivalent of: `"$1c$2c$3c$4c........$N"`, where 'c' is the first
character of `IFS`.
But when the `$@` special parameter is used inside double quotes, it
expands to the equivanent of\...
expands to the equivanent of...
`"$1" "$2" "$3" "$4" ..... "$N"`
\...which **reflects all positional parameters as they were set
...which **reflects all positional parameters as they were set
initially** and passed to the script or function. If you want to re-use
your positional parameters to **call another program** (for example in a
wrapper-script), then this is the choice for you, use double quoted
@ -234,12 +233,12 @@ reverse starting with the last one.
`COUNT` may not be negative, i.e. the element count may not be
decremented.
[**Example:**]{.underline} START at the last positional parameter:
<u>**Example:**</u> START at the last positional parameter:
echo "${@: -1}"
[**Attention**]{.underline}: As of Bash 4, a `START` of `0` includes the
special parameter `$0`, i.e. the shell name or whatever \$0 is set to,
<u>**Attention**</u>: As of Bash 4, a `START` of `0` includes the
special parameter `$0`, i.e. the shell name or whatever `$0` is set to,
when the positional parameters are in use. A `START` of `1` begins at
`$1`. In Bash 3 and older, both `0` and `1` began at `$1`.
@ -247,7 +246,7 @@ when the positional parameters are in use. A `START` of `1` begins at
Setting positional parameters with command line arguments, is not the
only way to set them. The [builtin command, set](../commands/builtin/set.md)
may be used to \"artificially\" change the positional parameters from
may be used to "artificially" change the positional parameters from
inside the script or function:
set "This is" my new "set of" positional parameters
@ -260,7 +259,7 @@ inside the script or function:
# $5: positional
# $6: parameters
It's wise to signal \"end of options\" when setting positional
It's wise to signal "end of options" when setting positional
parameters this way. If not, the dashes might be interpreted as an
option switch by `set` itself:
@ -273,7 +272,8 @@ flags, which may otherwise be reset by `set`
set -$- ...
FIXME continue
!!! warning "FIXME"
continue
## Production examples
@ -281,7 +281,7 @@ FIXME continue
To make your program accept options as standard command syntax:
`COMMAND [options] <params>` \# Like \'cat -A file.txt\'
`COMMAND [options] <params> # Like 'cat -A file.txt'`
See simple option parsing code below. It's not that flexible. It
doesn't auto-interpret combined options (-fu USER) but it works and is
@ -343,8 +343,8 @@ a good rudimentary way to parse your arguments.
This simple wrapper enables filtering unwanted options (here: `-a` and
`--all` for `ls`) out of the command line. It reads the positional
parameters and builds a filtered array consisting of them, then calls
`ls` with the new option set. It also respects the `--` as \"end of
options\" for `ls` and doesn't change anything after it:
`ls` with the new option set. It also respects the `--` as "end of
options" for `ls` and doesn't change anything after it:
#!/bin/bash

View File

@ -18,7 +18,7 @@ tree**. Every process has a parent process that started, or is
responsible, for it. Every process has its own **context memory** (Not
the memory where the process stores its data, rather, the memory where
data is stored that doesn't directly belong to the process, but is
needed to run the process) i.e. [**The environment**]{.underline}.
needed to run the process) i.e. <u>**The environment**</u>.
Every process has its **own** environment space.
@ -28,7 +28,7 @@ form, but they are not related to shell variables. A variable named
`LANG`, for example, is used by every program that looks it up in its
environment to determinate the current locale.
**[Attention:]{.underline}** A variable that is set, like with
<u>**Attention:**</u> A variable that is set, like with
`MYVAR=Hello`, is **not** automatically part of the environment. You
need to put it into the environment with the bash builtin command
`export`:
@ -41,30 +41,30 @@ set by login scripts or programs).
## Executing programs
All the diagrams of the process tree use names like \"`xterm`\" or
\"`bash`\", but that's just to make it easier to understand what's
All the diagrams of the process tree use names like "`xterm`" or
"`bash`", but that's just to make it easier to understand what's
going on, it doesn't mean those processes are actually executed.
Let's take a short look at what happens when you \"execute a program\"
from the Bash prompt, a program like \"ls\":
Let's take a short look at what happens when you "execute a program"
from the Bash prompt, a program like "ls":
$ ls
Bash will now perform **two steps**:
- It will make a copy of itself
- The copy will replace itself with the \"ls\" program
- The copy will replace itself with the "ls" program
The copy of Bash will inherit the environment from the \"main Bash\"
The copy of Bash will inherit the environment from the "main Bash"
process: All environment variables will also be copied to the new
process. This step is called **forking**.
For a short moment, you have a process tree that might look like
this\...
this...
xterm ----- bash ----- bash(copy)
\...and after the \"second Bash\" (the copy) replaces itself with the
...and after the "second Bash" (the copy) replaces itself with the
`ls` program (the copy execs it), it might look like
xterm ----- bash ----- ls
@ -73,10 +73,10 @@ If everything was okay, the two steps resulted in one program being run.
The copy of the environment from the first step (forking) becomes the
environment for the final running program (in this case, `ls`).
[**What is so important about it?**]{.underline} In our example, what
<u>**What is so important about it?**</u> In our example, what
the program `ls` does inside its own environment, it can't affect the
environment of its parent process (in this case, `bash`). The
environment was copied when ls was executed. Nothing is \"copied back\"
environment was copied when ls was executed. Nothing is "copied back"
to the parent environment when `ls` terminates.
## Bash playing with pipes
@ -84,7 +84,7 @@ to the parent environment when `ls` terminates.
Pipes are a very powerful tool. You can connect the output of one
process to the input of another process. We won't delve into piping at
this point, we just want to see how it looks in the process tree. Again,
we execute some commands, this time, we\'ll run `ls` and `grep`:
we execute some commands, this time, we'll run `ls` and `grep`:
$ ls | grep myfile
@ -98,7 +98,7 @@ Note once again, `ls` can't influence the `grep` environment, `grep`
can't influence the `ls` environment, and neither `grep` nor `ls` can
influence the `bash` environment.
[**How is that related to shell programming?!?**]{.underline}
<u>**How is that related to shell programming?!?**</u>
Well, imagine some Bash code that reads data from a pipe. For example,
the internal command `read`, which reads data from *stdin* and puts it
@ -120,12 +120,12 @@ it a bit, we have:
See the relationship? The forked Bash process will count the lines like
a charm. It will also set the variable `counter` as directed. But if
everything ends, this extra process will be terminated - **your
\"counter\" variable is gone.** You see a 0 because in the main shell it
"counter" variable is gone.** You see a 0 because in the main shell it
was 0, and wasn't changed by the child process!
[**So, how do we count the lines?**]{.underline} Easy: **Avoid the
<u>**So, how do we count the lines?**</u> Easy: **Avoid the
subshell.** The details don't matter, the important thing is the shell
that sets the counter must be the \"main shell\". For example:
that sets the counter must be the "main shell". For example:
counter=0
@ -185,4 +185,5 @@ pipe in the command substitution:
xterm ----- bash ----- bash (cmd. subst.) --|
+-- wc -l
FIXME to be continued
!!! warning "FIXME"
to be continued

View File

@ -1,14 +1,15 @@
# Scripting with style
FIXME continue
!!! warning "FIXME"
continue
These are some coding guidelines that helped me to read and understand
my own code over the years. They also will help to produce code that
will be a bit more robust than \"if something breaks, I know how to fix
it\".
will be a bit more robust than "if something breaks, I know how to fix
it".
This is not a bible, of course. But I have seen so much ugly and
terrible code (not only in shell) during all the years, that I\'m 100%
terrible code (not only in shell) during all the years, that I'm 100%
convinced there needs to be *some* code layout and style. No matter
which one you use, use it throughout your code (at least don't change
it within the same shellscript file); don't change your code layout
@ -22,7 +23,7 @@ of course it helps others to read the code.
Indentation is nothing that technically influences a script, it's only
for us humans.
I\'m used to seeing/using indentation of *two space characters* (though
I'm used to seeing/using indentation of *two space characters* (though
many may prefer 4 spaces, see below in the discussion section):
- it's easy and fast to type
@ -32,7 +33,7 @@ many may prefer 4 spaces, see below in the discussion section):
waste too much space on the line
Speaking of hard-tabs: Avoid them if possible. They only make trouble. I
can imagine one case where they\'re useful: Indenting
can imagine one case where they're useful: Indenting
[here-documents](../syntax/redirection.md#here_documents).
### Breaking up lines
@ -40,33 +41,33 @@ can imagine one case where they\'re useful: Indenting
Whenever you need to break lines of long code, you should follow one of
these two rules:
[**Indention using command width:**]{.underline}
<u>**Indention using command width:**</u>
activate some_very_long_option \
some_other_option
[**Indention using two spaces:**]{.underline}
<u>**Indention using two spaces:**</u>
activate some_very_long_option \
some_other_option
Personally, with some exceptions, I prefer the first form because it
supports the visual impression of \"these belong together\".
supports the visual impression of "these belong together".
### Breaking compound commands
[Compound commands](../syntax/ccmd/intro.md) form the structures that make a
shell script different from a stupid enumeration of commands. Usually
they contain a kind of \"head\" and a \"body\" that contains command
they contain a kind of "head" and a "body" that contains command
lists. This type of compound command is relatively easy to indent.
I\'m used to (not all points apply to all compound commands, just pick
I'm used to (not all points apply to all compound commands, just pick
the basic idea):
- put the introducing keyword and the initial command list or
parameters on one line (\"head\")
- put the \"body-introducing\" keyword on the same line
- the command list of the \"body\" on separate lines, indented by two
parameters on one line ("head")
- put the "body-introducing" keyword on the same line
- the command list of the "body" on separate lines, indented by two
spaces
- put the closing keyword on a separated line, indented like the
initial introducing keyword
@ -82,7 +83,7 @@ What?! Well, here again:
##### if/then/elif/else
This construct is a bit special, because it has keywords (`elif`,
`else`) \"in the middle\". The visually appealing way is to indent them
`else`) "in the middle". The visually appealing way is to indent them
like this:
if ...; then
@ -110,7 +111,7 @@ like this:
The `case` construct might need a bit more discussion here, since its
structure is a bit more complex.
In general, every new \"layer\" gets a new indentation level:
In general, every new "layer" gets a new indentation level:
case $input in
hello)
@ -149,13 +150,13 @@ It's - just like in C - the middle ground between smart, efficient and
readable.
If you need to use a cryptic construct, include a comment that explains
what your \"monster\" does.
what your "monster" does.
### Variable names
Since all reserved variables are `UPPERCASE`, the safest way is to only
use `lowercase` variable names. This is true for reading user input,
loop counting variables, etc., \... (in the example: `file`)
loop counting variables, etc., ... (in the example: `file`)
- prefer `lowercase` variables
- if you use `UPPERCASE` names, **do not use reserved variable names**
@ -165,9 +166,6 @@ loop counting variables, etc., \... (in the example: `file`)
- if you use `UPPERCASE` names, prepend the name with a unique prefix
(`MY_` in the example below)
```{=html}
<!-- -->
```
#!/bin/bash
# the prefix 'MY_'
@ -200,7 +198,7 @@ in-code documentation for them.
### Parameter expansion
Unless you are really sure what you\'re doing, **quote every parameter
Unless you are really sure what you're doing, **quote every parameter
expansion**.
There are some cases where this isn't needed from a technical point of
@ -212,7 +210,7 @@ view, e.g.
- variable assignment: `VAR=$WORD`
But quoting these is never a mistake. If you quote every parameter
expansion, you\'ll be safe.
expansion, you'll be safe.
If you need to parse a parameter as a list of words, you can't quote,
of course, e.g.
@ -252,8 +250,8 @@ should quote the command substitution!
### Eval
Well, like Greg says: **\"If eval is the answer, surely you are asking
the wrong question.\"**
Well, like Greg says: **"If eval is the answer, surely you are asking
the wrong question."**
Avoid it, unless absolutely neccesary:
@ -262,7 +260,7 @@ Avoid it, unless absolutely neccesary:
- if possible, re-think the way your script works, if it seems you
can't avoid `eval` with your current method
- if you really, really, have to use it, then take care, and be sure
about what you\'re doing
about what you're doing
## Basic structure
@ -281,8 +279,8 @@ The basic structure of a script simply reads:
If possible (I know it's not always possible!), use a
[shebang](../dict/interpreter_directive.md).
Be careful with `/bin/sh`: The argument that \"on Linux `/bin/sh` is
Bash\" **is a lie** (and technically irrelevant)
Be careful with `/bin/sh`: The argument that "on Linux `/bin/sh` is
Bash" **is a lie** (and technically irrelevant)
The shebang serves two purposes for me:
@ -290,16 +288,16 @@ The shebang serves two purposes for me:
called directly: If you code for Bash, specify `bash`!
- it documents the desired interpreter (so: use `bash` when you write
a Bash-script, use `sh` when you write a general Bourne/POSIX
script, \...)
script, ...)
### Configuration variables
I call variables that are meant to be changed by the user
\"configuration variables\" here.
"configuration variables" here.
Make them easy to find (directly at the top of the script), give them
meaningful names and maybe a short comment. As noted above, use
`UPPERCASE` for them only when you\'re sure about what you\'re doing.
`UPPERCASE` for them only when you're sure about what you're doing.
`lowercase` will be the safest.
### Function definitions
@ -310,7 +308,7 @@ overview and ensures that all function names are known before they are
used.
Since a function isn't parsed before it is executed, you usually don't
have to ensure they\'re in a specific order.
have to ensure they're in a specific order.
The portable form of the function definition should be used, without the
`function` keyword (here using the [grouping compound
@ -336,7 +334,7 @@ begins its work in a potentially broken state.
### Availability of commands
If you use external commands that may not be present on the path, or not
installed, check for their availability, then tell the user they\'re
installed, check for their availability, then tell the user they're
missing.
Example:
@ -370,9 +368,9 @@ means:
This, **and only this**, will enable the calling component to check the
operation status of your script.
You know: **\"One of the main causes of the fall of the Roman Empire was
You know: **"One of the main causes of the fall of the Roman Empire was
that, lacking zero, they had no way to indicate successful termination
of their C programs.\"** *-- Robert Firth*
of their C programs."** *-- Robert Firth*
## Misc
@ -405,5 +403,5 @@ of their C programs.\"** *-- Robert Firth*
### Tooling
- some of these guidelines, such as indentation, positioning of
\"body-introducing\" keywords, and portable function declarations,
"body-introducing" keywords, and portable function declarations,
can be enforced by [shfmt](https://github.com/mvdan/sh)

View File

@ -23,8 +23,8 @@ printed (like any other text). If the terminal understands the code, it
won't display the character-sequence, but will perform some action. You
can print the codes with a simple `echo` command.
[**Note:**]{.underline} I see codes referenced as \"Bash colors\"
sometimes (several \"Bash tutorials\" etc\...): That's a completely
<u>**Note:**</u> I see codes referenced as "Bash colors"
sometimes (several "Bash tutorials" etc...): That's a completely
incorrect definition.
## The tput command
@ -43,7 +43,7 @@ understands).
## The codes
In this list I\'ll focus on ANSI/VT100 control codes for the most common
In this list I'll focus on ANSI/VT100 control codes for the most common
actions - take it as quick reference. The documentation of your terminal
or the `terminfo` database is always the preferred source when something
is unclear! Also the `tput` acronyms are usually the ones dedicated for
@ -53,7 +53,7 @@ I listed only the most relevant codes, of course, any ANSI terminal
understands many more! But let's keep the discussion centered on common
shell scripting ;-)
If I couldn't find a matching ANSI escape, you\'ll see a :?: as the
If I couldn't find a matching ANSI escape, you'll see a :?: as the
code. Feel free to mail me or fix it.
The ANSI codes always start with the ESC character. (ASCII 0x1B or octal
@ -63,29 +63,29 @@ codes directly - use the `tput` command!**
All codes that can be used with `tput` can be found in terminfo(5). (on
OpenBSD at least) See [OpenBSD's
terminfo(5)](http://www.openbsd.org/cgi-bin/man.cgi?query=terminfo&apropos=0&sektion=5&manpath=OpenBSD+Current&arch=i386&format=html)
under the [Capabilities]{.underline} section. The *cap-name* is the code
under the <u>Capabilities</u> section. The *cap-name* is the code
to use with tput. A description of each code is also provided.
### General useful ASCII codes
The **Ctrl-Key** representation is simply associating the non-printable
characters from ASCII code 1 with the printable (letter) characters from
ASCII code 65 (\"A\"). ASCII code 1 would be `^A` (Ctrl-A), while ASCII
ASCII code 65 ("A"). ASCII code 1 would be `^A` (Ctrl-A), while ASCII
code 7 (BEL) would be `^G` (Ctrl-G). This is a common representation
(and input method) and historically comes from one of the VT series of
terminals.
Name decimal octal hex C-escape Ctrl-Key Description
------- --------- ------- ------ ---------- ---------- --------------------------------
`BEL` 7 007 0x07 `\a` `^G` Terminal bell
`BS` 8 010 0x08 `\b` `^H` Backspace
`HT` 9 011 0x09 `\t` `^I` Horizontal TAB
`LF` 10 012 0x0A `\n` `^J` Linefeed (newline)
`VT` 11 013 0x0B `\v` `^K` Vertical TAB
`FF` 12 014 0x0C `\f` `^L` Formfeed (also: New page `NP`)
`CR` 13 015 0x0D `\r` `^M` Carriage return
`ESC` 27 033 0x1B `<none>` `^[` Escape character
`DEL` 127 177 0x7F `<none>` `<none>` Delete character
|Name|decimal|octal|hex|C-escape|Ctrl-Key|Description|
|-------|---------|-------|------|----------|----------|--------------------------------|
|`BEL`|7|007|0x07|`\a`|`^G`|Terminal bell|
|`BS`|8|010|0x08|`\b`|`^H`|Backspace|
|`HT`|9|011|0x09|`\t`|`^I`|Horizontal TAB|
|`LF`|10|012|0x0A|`\n`|`^J`|Linefeed (newline)|
|`VT`|11|013|0x0B|`\v`|`^K`|Vertical TAB|
|`FF`|12|014|0x0C|`\f`|`^L`|Formfeed (also: New page `NP`)|
|`CR`|13|015|0x0D|`\r`|`^M`|Carriage return|
|`ESC`|27|033|0x1B|`<none>`|`^[`|Escape character|
|`DEL`|127|177|0x7F|`<none>`|`<none>`|Delete character|
### Cursor handling
@ -123,44 +123,43 @@ terminals.
### General text attributes
ANSI terminfo equivalent Description
--------- ----------------------------- ------------------------------------------------
`[ 0 m` `sgr0` Reset all attributes
`[ 1 m` `bold` Set \"bright\" attribute
`[ 2 m` `dim` Set \"dim\" attribute
`[ 3 m` `smso` Set \"standout\" attribute
`[ 4 m` set `smul` unset `rmul` :?: Set \"underscore\" (underlined text) attribute
`[ 5 m` `blink` Set \"blink\" attribute
`[ 7 m` `rev` Set \"reverse\" attribute
`[ 8 m` `invis` Set \"hidden\" attribute
|ANSI|terminfo equivalent|Description|
|----|-------------------|-----------|
|`[ 0 m`|`sgr0`|Reset all attributes|
|`[ 1 m`|`bold`|Set "bright" attribute|
|`[ 2 m`|`dim`|Set "dim" attribute|
|`[ 3 m`|`smso`|Set "standout" attribute|
|`[ 4 m`|set `smul` unset `rmul` :?:|Set "underscore" (underlined text) attribute|
|`[ 5 m`|`blink`|Set "blink" attribute|
|`[ 7 m`|`rev`|Set "reverse" attribute|
|`[ 8 m`|`invis`|Set "hidden" attribute|
### Foreground coloring
ANSI terminfo equivalent Description
----------- --------------------- ----------------------------------------------
`[ 3 0 m` `setaf 0` Set **foreground** to color #0 - **black**
`[ 3 1 m` `setaf 1` Set **foreground** to color #1 - **red**
`[ 3 2 m` `setaf 2` Set **foreground** to color #2 - **green**
`[ 3 3 m` `setaf 3` Set **foreground** to color #3 - **yellow**
`[ 3 4 m` `setaf 4` Set **foreground** to color #4 - **blue**
`[ 3 5 m` `setaf 5` Set **foreground** to color #5 - **magenta**
`[ 3 6 m` `setaf 6` Set **foreground** to color #6 - **cyan**
`[ 3 7 m` `setaf 7` Set **foreground** to color #7 - **white**
`[ 3 9 m` `setaf 9` Set **default** color as foreground color
|ANSI|terminfo equivalent|Description|
|----|-------------------|-----------|
|`[ 3 0 m`|`setaf 0`|Set **foreground** to color \#0 - **black**|
|`[ 3 1 m`|`setaf 1`|Set **foreground** to color \#1 - **red**|
|`[ 3 2 m`|`setaf 2`|Set **foreground** to color \#2 - **green**|
|`[ 3 3 m`|`setaf 3`|Set **foreground** to color \#3 - **yellow**|
|`[ 3 4 m`|`setaf 4`|Set **foreground** to color \#4 - **blue**|
|`[ 3 5 m`|`setaf 5`|Set **foreground** to color \#5 - **magenta**|
|`[ 3 6 m`|`setaf 6`|Set **foreground** to color \#6 - **cyan**|
|`[ 3 7 m`|`setaf 7`|Set **foreground** to color \#7 - **white**|
|`[ 3 9 m`|`setaf 9`|Set **default** color as foreground color|
### Background coloring
ANSI terminfo equivalent Description
----------- --------------------- ----------------------------------------------
`[ 4 0 m` `setab 0` Set **background** to color #0 - **black**
`[ 4 1 m` `setab 1` Set **background** to color #1 - **red**
`[ 4 2 m` `setab 2` Set **background** to color #2 - **green**
`[ 4 3 m` `setab 3` Set **background** to color #3 - **yellow**
`[ 4 4 m` `setab 4` Set **background** to color #4 - **blue**
`[ 4 5 m` `setab 5` Set **background** to color #5 - **magenta**
`[ 4 6 m` `setab 6` Set **background** to color #6 - **cyan**
`[ 4 7 m` `setab 7` Set **background** to color #7 - **white**
`[ 4 9 m` `setab 9` Set **default** color as background color
|ANSI|terminfo equivalent|Description|
|----|-------------------|-----------|
|`[ 4 0 m`|`setab 0`|Set **background** to color \#0 - **black**|
|`[ 4 1 m`|`setab 1`|Set **background** to color \#1 - **red**|
|`[ 4 2 m`|`setab 2`|Set **background** to color \#2 - **green**|
|`[ 4 3 m`|`setab 3`|Set **background** to color \#3 - **yellow**|
|`[ 4 4 m`|`setab 4`|Set **background** to color \#4 - **blue**|
|`[ 4 5 m`|`setab 5`|Set **background** to color \#5 - **magenta**|
|`[ 4 6 m`|`setab 6`|Set **background** to color \#6 - **cyan**|
|`[ 4 7 m`|`setab 7`|Set **background** to color \#7 - **white**|
|`[ 4 9 m`|`setab 9`|Set **default** color as background color|
### Misc codes
@ -168,7 +167,7 @@ terminals.
Used capabilities: `smcup`, `rmcup`
You\'ve undoubtedly already encountered programs that restore the
You've undoubtedly already encountered programs that restore the
terminal contents after they do their work (like `vim`). This can be
done by the following commands:
@ -187,7 +186,7 @@ These features require that certain capabilities exist in your
termcap/terminfo. While `xterm` and most of its clones (`rxvt`, `urxvt`,
etc) will support the instructions, your operating system may not
include references to them in its default xterm profile. (FreeBSD, in
particular, falls into this category.) If \`tput smcup\` appears to do
particular, falls into this category.) If `tput smcup` appears to do
nothing for you, and you don't want to modify your system
termcap/terminfo data, and you KNOW that you are using a compatible
xterm application, the following may work for you:
@ -198,14 +197,14 @@ xterm application, the following may work for you:
Certain software uses these codes (via their termcap capabilities) as
well. You may have seen the screen save/restore in `less`, `vim`, `top`,
`screen` and others. Some of these applications may also provide
configuration options to \*disable\* this behaviour. For example, `less`
configuration options to *disable* this behaviour. For example, `less`
has a `-X` option for this, which can also be set in an environment
variable:
export LESS=X
less /path/to/file
Similarly, `vim` can be configured not to \"restore\" the screen by
Similarly, `vim` can be configured not to "restore" the screen by
adding the following to your `~/.vimrc`:
set t_ti= t_te=
@ -226,7 +225,7 @@ in graphical environments.
The Virtual Terminal implemented in the Linux kernel supports only 16
colors, and the usual default terminfo entry for `TERM=linux` defines
only 8. There is sometimes an alternate \"linux-16color\" that you can
only 8. There is sometimes an alternate "linux-16color" that you can
switch to, to get the other 8 colors.
## Bash examples
@ -237,11 +236,11 @@ switch to, to get the other 8 colors.
### Colors using tput
[Directly inside the echo:]{.underline}
<u>Directly inside the echo:</u>
echo "TPUT is a $(tput setaf 2)nice$(tput setaf 9) and $(tput setaf 5)user friendly$(tput setaf 9) terminal capability database."
[With preset variables:]{.underline}
<u>With preset variables:</u>
COL_NORM="$(tput setaf 9)"
COL_RED="$(tput setaf 1)"
@ -250,7 +249,7 @@ switch to, to get the other 8 colors.
### Misc
[HOME function]{.underline}
<u>HOME function</u>
home() {
# yes, actually not much shorter ;-)

View File

@ -16,7 +16,7 @@ This example queries the hostkeys for the very same machine, but under 3
different \"names\" (hostname, FQDN, IP) and redirects the output to the
`known_hosts`-file.
[**Notes:**]{.underline}
<u>**Notes:**</u>
- if done blindly, the `known_host`-file may grow very large. It might
be wise to check for key existance first

View File

@ -31,7 +31,7 @@ then this script should generate code that looks like
you need correct escapes or quotes to not generate shell special
characters out of normal text (like embedded dollar signs `$`).
**[Solution:]{.underline}**
**<u>Solution:</u>**
A loop over the own arguments that writes out properly quoted/escaped
code to the generated script file

View File

@ -74,7 +74,7 @@ When no base is specified, the base 10 (decimal) is assumed, except when
the prefixes as mentioned above (octals, hexadecimals) are present. The
specified base can range from 2 to 64. To represent digits in a
specified base greater than 10, characters other than 0 to 9 are needed
(in this order, low => high):
(in this order, low =&gt; high):
- `0 ... 9`
- `a ... z`
@ -124,8 +124,8 @@ named parameters, e.g.:
# will output "3"!
Of course, in the end, when it finally evaluates to something that is
**not** a valid arithmetic expression (newlines, ordinary text, \...)
then you\'ll get an error.
**not** a valid arithmetic expression (newlines, ordinary text, ...)
then you'll get an error.
When variables are referenced, the notation `1 + $X` is equivalent to
the notation `1 + X`, both are allowed.
@ -138,10 +138,10 @@ an arithmetic expression.
## Truth
Unlike command exit and return codes, arithmetic expressions evaluate to
logical \"true\" when they are not 0. When they are 0, they evaluate to
\"false\". The [arithmetic evaluation compound
command](../syntax/ccmd/arithmetic_eval.md) reverses the \"truth\" of an
arithmetic expression to match the \"truth\" of command exit codes:
logical "true" when they are not 0. When they are 0, they evaluate to
"false". The [arithmetic evaluation compound
command](../syntax/ccmd/arithmetic_eval.md) reverses the "truth" of an
arithmetic expression to match the "truth" of command exit codes:
- if the arithmetic expression brings up a value not 0 (arithmetic
true), it returns 0 (shell true)
@ -160,89 +160,79 @@ That means, the following `if`-clause will execute the `else`-thread:
### Assignment
Operator Description
--------------------- ----------------------------------------------------------------------------------------------------
`<ID> = <EXPR>` normal assignment
`<ID> *= <EXPR>` equivalent to `<ID> = <ID> * <EXPR>`, see [calculation operators](../syntax/arith_expr.md#calculations)
`<ID> /= <EXPR>` equivalent to `<ID> = <ID> / <EXPR>`, see [calculation operators](../syntax/arith_expr.md#calculations)
`<ID> %= <EXPR>` equivalent to `<ID> = <ID> % <EXPR>`, see [calculation operators](../syntax/arith_expr.md#calculations)
`<ID> += <EXPR>` equivalent to `<ID> = <ID> + <EXPR>`, see [calculation operators](../syntax/arith_expr.md#calculations)
`<ID> -= <EXPR>` equivalent to `<ID> = <ID> - <EXPR>`, see [calculation operators](../syntax/arith_expr.md#calculations)
`<ID> <<= <NUMBER>` equivalent to `<ID> = <ID> << <NUMBER>`, see [bit operations](../syntax/arith_expr.md#bit_operations)
`<ID> >>= <NUMBER>` equivalent to `<ID> = <ID> >> <NUMBER>`, see [bit operations](../syntax/arith_expr.md#bit_operations)
`<ID> &= <EXPR>` equivalent to `<ID> = <ID> & <EXPR>`, see [bit operations](../syntax/arith_expr.md#bit_operations)
`<ID> ^= <EXPR>` equivalent to `<ID> = <ID> ^ <EXPR>`, see [bit operations](../syntax/arith_expr.md#bit_operations)
`<ID> |= <EXPR>` equivalent to `<ID> = <ID> | <EXPR>`, see [bit operations](../syntax/arith_expr.md#bit_operations)
|Operator|Description|
|--------|-----------|
|`<ID> = <EXPR>`|normal assignment|
|`<ID> *= <EXPR>`|equivalent to `<ID> = <ID> * <EXPR>`, see [calculation operators](../syntax/arith_expr.md#calculations)|
|`<ID> /= <EXPR>`|equivalent to `<ID> = <ID> / <EXPR>`, see [calculation operators](../syntax/arith_expr.md#calculations)|
|`<ID> %= <EXPR>`|equivalent to `<ID> = <ID> % <EXPR>`, see [calculation operators](../syntax/arith_expr.md#calculations)|
|`<ID> += <EXPR>`|equivalent to `<ID> = <ID> + <EXPR>`, see [calculation operators](../syntax/arith_expr.md#calculations)|
|`<ID> -= <EXPR>`|equivalent to `<ID> = <ID> - <EXPR>`, see [calculation operators](../syntax/arith_expr.md#calculations)|
|`<ID> <<= <NUMBER>`|equivalent to `<ID> = <ID> << <NUMBER>`, see [bit operations](../syntax/arith_expr.md#bit_operations)|
|`<ID> >>= <NUMBER>`|equivalent to `<ID> = <ID> >> <NUMBER>`, see [bit operations](../syntax/arith_expr.md#bit_operations)|
|`<ID> &= <EXPR>`|equivalent to `<ID> = <ID> & <EXPR>`, see [bit operations](../syntax/arith_expr.md#bit_operations)|
|`<ID> ^= <EXPR>`|equivalent to `<ID> = <ID> ^ <EXPR>`, see [bit operations](../syntax/arith_expr.md#bit_operations)|
|`<ID>|= <EXPR>`|equivalent to `<ID> = <ID>|<EXPR>`, see [bit operations](../syntax/arith_expr.md#bit_operations)|
### Calculations
Operator Description
---------- --------------------
`*` multiplication
`/` division
`%` remainder (modulo)
`+` addition
`-` subtraction
`**` exponentiation
|Operator|Description|
|--------|-----------|
|`*`|multiplication|
|`/`|division|
|`%`|remainder (modulo)|
|`+`|addition|
|`-`|subtraction|
|`**`|exponentiation|
### Comparisons
Operator Description
---------- -----------------------------------
`<` comparison: less than
`>` comparison: greater than
`<=` comparison: less than or equal
`>=` comparison: greater than or equal
`==` equality
`!=` inequality
|Operator|Description|
|--------|-----------|
|`<`|comparison: less than|
|`>`|comparison: greater than|
|`<=`|comparison: less than or equal|
|`>=`|comparison: greater than or equal|
|`==`|equality|
|`!=`|inequality|
### Bit operations
Operator Description
---------- ----------------------------
`~` bitwise negation
`<<` bitwise shifting (left)
`>>` bitwise shifting (right)
`&` bitwise AND
`^` bitwise exclusive OR (XOR)
`|` bitwise OR
|Operator|Description|
|--------|-----------|
|`~`|bitwise negation|
|`<<`|bitwise shifting (left)|
|`>>`|bitwise shifting (right)|
|`&`|bitwise AND|
|`^`|bitwise exclusive OR (XOR)|
|`|`|bitwise OR|
### Logical
Operator Description
---------- ------------------
`!` logical negation
`&&` logical AND
`||` logical OR
|Operator|Description|
|--------|-----------|
|`!`|logical negation|
|`&&`|logical AND|
|`||`|logical OR|
### Misc
-------------------------------------------------------------------------------------------------
Operator Description
---------------------------- --------------------------------------------------------------------
`id++` **post-increment** of the variable `id` (not required by POSIX(r))
`id--` **post-decrement** of the variable `id` (not required by POSIX(r))
`++id` **pre-increment** of the variable `id` (not required by POSIX(r))
`--id` **pre-decrement** of the variable `id` (not required by POSIX(r))
`+` unary plus
`-` unary minus
`<EXPR> ? <EXPR> : <EXPR>` conditional (ternary) operator\
<condition> ? <result-if-true> : <result-if-false>
`<EXPR> , <EXPR>` expression list
`( <EXPR> )` subexpression (to force precedence)
-------------------------------------------------------------------------------------------------
|Operator|Description|
|--------|-----------|
|`id++`|**post-increment** of the variable `id` (not required by POSIX(r))|
|`id--`|**post-decrement** of the variable `id` (not required by POSIX(r))|
|`++id`|**pre-increment** of the variable `id` (not required by POSIX(r))|
|`--id`|**pre-decrement** of the variable `id` (not required by POSIX(r))|
|`+`|unary plus|
|`-`|unary minus|
|`<EXPR> ? <EXPR> : <EXPR>`|conditional (ternary) operator &lt;condition&gt; ? &lt;result-if-true&gt; : &lt;result-if-false&gt;|
|`<EXPR> , <EXPR>`|expression list|
|`( <EXPR> )`|subexpression (to force precedence)|
## Precedence
The operator precedence is as follows (highest -> lowest):
The operator precedence is as follows (highest -&gt; lowest):
- Postfix (`id++`, `id--`)
- Prefix (`++id`, `--id`)
@ -274,19 +264,19 @@ Bash's overall language construct is based on exit codes or return
codes of commands or functions to be executed. `if` statements, `while`
loops, etc., they all take the return codes of commands as conditions.
Now the problem is: The return codes (0 means \"TRUE\" or \"SUCCESS\",
not 0 means \"FALSE\" or \"FAILURE\") don't correspond to the meaning
of the result of an arithmetic expression (0 means \"FALSE\", not 0
means \"TRUE\").
Now the problem is: The return codes (0 means "TRUE" or "SUCCESS",
not 0 means "FALSE" or "FAILURE") don't correspond to the meaning
of the result of an arithmetic expression (0 means "FALSE", not 0
means "TRUE").
That's why all commands and keywords that do arithmetic operations
attempt to **translate** the arithmetical meaning into an equivalent
return code. This simply means:
- if the arithmetic operation evaluates to 0 (\"FALSE\"), the return
code is not 0 (\"FAILURE\")
- if the arithmetic operation evaluates to 1 (\"TRUE\"), the return
code is 0 (\"SUCCESS\")
- if the arithmetic operation evaluates to 0 ("FALSE"), the return
code is not 0 ("FAILURE")
- if the arithmetic operation evaluates to 1 ("TRUE"), the return
code is 0 ("SUCCESS")
This way, you can easily use arithmetic expressions (along with the
commands or keywords that operate them) as conditions for `if`, `while`
@ -302,47 +292,48 @@ else
fi
```
<WRAP center round important> Beware that `set -e` can change the
runtime behavior of scripts. For example,
!!! warning "Beware that `set -e` can change the runtime behavior of scripts."
This non-equivalence of code behavior deserves some attention. Consider
what happens if v happens to be zero in the expression below:
For example,
``` bash
((v += 0))
echo $?
```
This non-equivalence of code behavior deserves some attention. Consider
what happens if v happens to be zero in the expression below:
1
``` bash
((v += 0))
echo $?
```
(\"FAILURE\")
1
``` bash
v=$((v + 0))
echo $?
```
("FAILURE")
0
``` bash
v=$((v + 0))
echo $?
```
(\"SUCCESS\")
0
The return code behavior is not equivalent to the arithmetic behavior,
as has been noted.
("SUCCESS")
A workaround is to use a list operation that returns True, or use the
second assignment style.
The return code behavior is not equivalent to the arithmetic behavior,
as has been noted.
``` bash
((v += 0)) || :
echo $?
```
A workaround is to use a list operation that returns True, or use the
second assignment style.
0
``` bash
((v += 0)) || :
echo $?
```
(\"SUCCESS\")
0
This change in code behavior was discovered once the script was run
under set -e. </WRAP>
("SUCCESS")
This change in code behavior was discovered once the script was run
under set -e.
## Arithmetic expressions in Bash
@ -350,4 +341,4 @@ under set -e. </WRAP>
- [Arithmetic expansion](../syntax/expansion/arith.md)
- [Arithmetic evaluation compound
command](../syntax/ccmd/arithmetic_eval.md)
- [The \"let\" builtin command](../commands/builtin/let.md)
- [The "let" builtin command](../commands/builtin/let.md)

View File

@ -38,7 +38,7 @@ Bash supports two different types of ksh-like one-dimensional arrays.
ksh88. Similar, partially compatible syntax was inherited by many
derivatives including Bash. Indexed arrays always carry the `-a`
attribute.
- *Associative arrays* (sometimes known as a \"hash\" or \"dict\") use
- *Associative arrays* (sometimes known as a "hash" or "dict") use
arbitrary nonempty strings as keys. In other words, associative
arrays allow you to look up a value from a table based upon its
corresponding string label. **Associative arrays are always
@ -99,12 +99,12 @@ an array without assigning any values (see [declaration](#Declaration)).
The following explicitly give variables array attributes, making them
arrays:
Syntax Description
-------------------- -------------------------------------------------------------------------------------------------------------------------
`ARRAY=()` Declares an **indexed** array `ARRAY` and initializes it to be empty. This can also be used to empty an existing array.
`ARRAY[0]=` Generally sets the first element of an **indexed** array. If no array `ARRAY` existed before, it is created.
`declare -a ARRAY` Declares an **indexed** array `ARRAY`. An existing array is not initialized.
`declare -A ARRAY` Declares an **associative** array `ARRAY`. This is the one and only way to create associative arrays.
|Syntax|Description|
|------|-----------|
|`ARRAY=()`|Declares an **indexed** array `ARRAY` and initializes it to be empty. This can also be used to empty an existing array.|
|`ARRAY[0]=`|Generally sets the first element of an **indexed** array. If no array `ARRAY` existed before, it is created.|
|`declare -a ARRAY`|Declares an **indexed** array `ARRAY`. An existing array is not initialized.|
|`declare -A ARRAY`|Declares an **associative** array `ARRAY`. This is the one and only way to create associative arrays.|
As an example, and for use below, let's declare our `NAMES` array as
described [above](#purpose):
@ -116,31 +116,32 @@ described [above](#purpose):
Storing values in arrays is quite as simple as storing values in normal
variables.
Syntax Description
--------------------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
`ARRAY[N]=VALUE` Sets the element `N` of the **indexed** array `ARRAY` to `VALUE`. **`N` can be any valid [arithmetic expression](../syntax/arith_expr.md)**.
`ARRAY[STRING]=VALUE` Sets the element indexed by `STRING` of the **associative array** `ARRAY`.
`ARRAY=VALUE` As above. If no index is given, as a default the zeroth element is set to `VALUE`. Careful, this is even true of associative arrays - there is no error if no key is specified, and the value is assigned to string index \"0\".
`ARRAY=(E1\ E2\ ...)` Compound array assignment - sets the whole array `ARRAY` to the given list of elements indexed sequentially starting at zero. The array is unset before assignment unless the += operator is used. When the list is empty (`ARRAY=()`), the array will be set to an empty array. This method obviously does not use explicit indexes. An **associative array** can **not** be set like that! Clearing an associative array using `ARRAY=()` works.
`ARRAY=([X]=E1\ [Y]=E2\ ...)` Compound assignment for indexed arrays with index-value pairs declared individually (here for example `X` and `Y`). X and Y are arithmetic expressions. This syntax can be combined with the above - elements declared without an explicitly specified index are assigned sequentially starting at either the last element with an explicit index, or zero.
`ARRAY=([S1]=E1\ [S2]=E2\ ...)` Individual mass-setting for **associative arrays**. The named indexes (here: `S1` and `S2`) are strings.
`ARRAY+=(E1\ E2\ ...)` Append to ARRAY.
`ARRAY=("${ANOTHER_ARRAY[@]}")` Copy ANOTHER_ARRAY to ARRAY, copying each element.
|Syntax|Description|
|------|-----------|
|`ARRAY[N]=VALUE`|Sets the element `N` of the **indexed** array `ARRAY` to `VALUE`. **`N` can be any valid [arithmetic expression](../syntax/arith_expr.md)**.|
|`ARRAY[STRING]=VALUE`|Sets the element indexed by `STRING` of the **associative array** `ARRAY`.|
|`ARRAY=VALUE`|As above. If no index is given, as a default the zeroth element is set to `VALUE`. Careful, this is even true of associative arrays - there is no error if no key is specified, and the value is assigned to string index "0".|
|`ARRAY=(E1\ E2\ ...)`|Compound array assignment - sets the whole array `ARRAY` to the given list of elements indexed sequentially starting at zero. The array is unset before assignment unless the += operator is used. When the list is empty (`ARRAY=()`), the array will be set to an empty array. This method obviously does not use explicit indexes. An **associative array** can **not** be set like that! Clearing an associative array using `ARRAY=()` works.|
|`ARRAY=([X]=E1\ [Y]=E2\ ...)`|Compound assignment for indexed arrays with index-value pairs declared individually (here for example `X` and `Y`). X and Y are arithmetic expressions. This syntax can be combined with the above - elements declared without an explicitly specified index are assigned sequentially starting at either the last element with an explicit index, or zero.|
|`ARRAY=([S1]=E1\ [S2]=E2\ ...)`|Individual mass-setting for **associative arrays**. The named indexes (here: `S1` and `S2`) are strings.|
|`ARRAY+=(E1\ E2\ ...)`|Append to ARRAY.|
|`ARRAY=("${ANOTHER_ARRAY[@]}")`|Copy ANOTHER_ARRAY to ARRAY, copying each element.|
As of now, arrays can't be exported.
### Getting values
<note> For completeness and details on several parameter expansion
variants, see the [article about parameter expansion](../syntax/pe.md) and
check the notes about arrays. </note>
!!! info ""
For completeness and details on several parameter expansion
variants, see the [article about parameter expansion](../syntax/pe.md) and
check the notes about arrays.
Syntax Description
----------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
`${ARRAY[N]}` Expands to the value of the index `N` in the **indexed** array `ARRAY`. If `N` is a negative number, it's treated as the offset from the maximum assigned index (can't be used for assignment) - 1
`${ARRAY[S]}` Expands to the value of the index `S` in the **associative** array `ARRAY`.
`"${ARRAY[@]}" ${ARRAY[@]} "${ARRAY[*]}" ${ARRAY[*]}` Similar to [mass-expanding positional parameters](../scripting/posparams.md#mass_usage), this expands to all elements. If unquoted, both subscripts `*` and `@` expand to the same result, if quoted, `@` expands to all elements individually quoted, `*` expands to all elements quoted as a whole.
`"${ARRAY[@]:N:M}" ${ARRAY[@]:N:M} "${ARRAY[*]:N:M}" ${ARRAY[*]:N:M}` Similar to what this syntax does for the characters of a single string when doing [substring expansion](../syntax/pe.md#substring_expansion), this expands to `M` elements starting with element `N`. This way you can mass-expand individual indexes. The rules for quoting and the subscripts `*` and `@` are the same as above for the other mass-expansions.
|Syntax|Description|
|------|-----------|
|`${ARRAY[N]}`|Expands to the value of the index `N` in the **indexed** array `ARRAY`. If `N` is a negative number, it's treated as the offset from the maximum assigned index (can't be used for assignment) - 1|
|`${ARRAY[S]}`|Expands to the value of the index `S` in the **associative** array `ARRAY`.|
|`"${ARRAY[@]}" ${ARRAY[@]} "${ARRAY[*]}" ${ARRAY[*]}`|Similar to [mass-expanding positional parameters](../scripting/posparams.md#mass_usage), this expands to all elements. If unquoted, both subscripts `*` and `@` expand to the same result, if quoted, `@` expands to all elements individually quoted, `*` expands to all elements quoted as a whole.|
|`"${ARRAY[@]:N:M}" ${ARRAY[@]:N:M} "${ARRAY[*]:N:M}" ${ARRAY[*]:N:M}`|Similar to what this syntax does for the characters of a single string when doing [substring expansion](../syntax/pe.md#substring_expansion), this expands to `M` elements starting with element `N`. This way you can mass-expand individual indexes. The rules for quoting and the subscripts `*` and `@` are the same as above for the other mass-expansions.|
For clarification: When you use the subscripts `@` or `*` for
mass-expanding, then the behaviour is exactly what it is for `$@` and
@ -150,62 +151,50 @@ article to understand what's going on.
### Metadata
--------------------------------------------------------------------------------------------------------------------------------
Syntax Description
--------------------- ----------------------------------------------------------------------------------------------------------
`${#ARRAY[N]}` Expands to the **length** of an individual array member at index `N` (**stringlength**)
`${#ARRAY[STRING]}` Expands to the **length** of an individual associative array member at index `STRING` (**stringlength**)
`${#ARRAY[@]}`\ Expands to the **number of elements** in `ARRAY`
`${#ARRAY[*]}`
`${!ARRAY[@]}`\ Expands to the **indexes** in `ARRAY` since BASH 3.0
`${!ARRAY[*]}`
--------------------------------------------------------------------------------------------------------------------------------
|Syntax|Description|
|------|-----------|
|`${#ARRAY[N]}`|Expands to the **length** of an individual array member at index `N` (**stringlength**)|
|`${#ARRAY[STRING]}`|Expands to the **length** of an individual associative array member at index `STRING` (**stringlength**)|
|`${#ARRAY[@]}` \ `${#ARRAY[*]}`|Expands to the **number of elements** in `ARRAY`|
|`${!ARRAY[@]}` \ `${!ARRAY[*]}`|Expands to the **indexes** in `ARRAY` since BASH 3.0|
### Destruction
The [unset](../commands/builtin/unset.md) builtin command is used to destroy
(unset) arrays or individual elements of arrays.
--------------------------------------------------------------------------------------------------
Syntax Description
-------------------------- -----------------------------------------------------------------------
`unset -v ARRAY`\ Destroys a complete array
`unset -v ARRAY[@]`\
`unset -v ARRAY[*]`
`unset -v ARRAY[N]` Destroys the array element at index `N`
`unset -v ARRAY[STRING]` Destroys the array element of the associative array at index `STRING`
--------------------------------------------------------------------------------------------------
|Syntax|Description|
|------|-----------|
|`unset -v ARRAY` \ `unset -v ARRAY[@]` \ `unset -v ARRAY[*]`|Destroys a complete array|
|`unset -v ARRAY[N]`|Destroys the array element at index `N`|
|`unset -v ARRAY[STRING]`|Destroys the array element of the associative array at index `STRING`|
It is best to [explicitly specify
-v](../commands/builtin/unset.md#portability_considerations) when unsetting
variables with unset.
<note warning> Specifying unquoted array elements as arguments to any
command, such as with the syntax above **may cause [pathname
expansion](../syntax/expansion/globs.md) to occur** due to the presence of
glob characters.
!!! warning "warning"
Specifying unquoted array elements as arguments to any
command, such as with the syntax above **may cause [pathname
expansion](../syntax/expansion/globs.md) to occur** due to the presence of
glob characters.
Example: You are in a directory with a file named `x1`, and you want to
destroy an array element `x[1]`, with
Example: You are in a directory with a file named `x1`, and you want to
destroy an array element `x[1]`, with
unset x[1]
unset x[1]
then pathname expansion will expand to the filename `x1` and break your
processing!
then pathname expansion will expand to the filename `x1` and break your
processing!
Even worse, if `nullglob` is set, your array/index will disappear.
Even worse, if `nullglob` is set, your array/index will disappear.
To avoid this, **always quote** the array name and index:
To avoid this, **always quote** the array name and index:
unset -v 'x[1]'
unset -v 'x[1]'
This applies generally to all commands which take variable names as
arguments. Single quotes preferred. </note>
This applies generally to all commands which take variable names as
arguments. Single quotes preferred.
## Usage
@ -247,7 +236,7 @@ The method above, walking through an array by just knowing its number of
elements, only works for arrays where all elements are set, of course.
If one element in the middle is removed, then the calculation is
nonsense, because the number of elements doesn't correspond to the
highest used index anymore (we call them \"*sparse arrays*\").
highest used index anymore (we call them "*sparse arrays*").
Now, suppose that you want to replace your array `sentence` with the
values in the [previously-declared array](#purpose) `NAMES` . You might
@ -297,7 +286,7 @@ starting at zero) just is replaced with an arbitrary string:
sentence[End]='in what you send'
sentence['Very end']=...
[**Beware:**]{.underline} don't rely on the fact that the elements are
<u>**Beware:**</u> don't rely on the fact that the elements are
ordered in memory like they were declared, it could look like this:
# output from 'set' command
@ -369,13 +358,13 @@ strings would have been inserted into the integer array without
evaluating the arithmetic. A special-case of this is shown in the next
section.
<note> Bash declaration commands are really keywords in disguise. They
magically parse arguments to determine whether they are in the form of a
valid assignment. If so, they are evaluated as assignments. If not, they
are undergo normal argument expansion before being passed to the builtin
which evaluates the resulting string as an assignment (somewhat like
`eval`, but there are differences.) `'Todo:`\' Discuss this in detail.
</note>
!!! info "info"
Bash declaration commands are really keywords in disguise. They
magically parse arguments to determine whether they are in the form of a
valid assignment. If so, they are evaluated as assignments. If not, they
are undergo normal argument expansion before being passed to the builtin
which evaluates the resulting string as an assignment (somewhat like
`eval`, but there are differences.) `'Todo:`\' Discuss this in detail.
### Indirection
@ -385,7 +374,7 @@ syntax. Parameters whose values are of the form: `name[index]`,
results. This is mainly useful for passing arrays (especially multiple
arrays) by name to a function.
This example is an \"isSubset\"-like predicate which returns true if all
This example is an "isSubset"-like predicate which returns true if all
key-value pairs of the array given as the first argument to isSubset
correspond to a key-value of the array given as the second argument. It
demonstrates both indirect array expansion and indirect key-passing
@ -550,7 +539,7 @@ dynamically calls a function whose name is resolved from the array.
the subscript or the value first can change in almost every shell
for both expansions and arithmetic variables. See [evaluation
order](#evaluation_order) for details.
- Bash 4.1.\* and below cannot use negative subscripts to address
- Bash 4.1.* and below cannot use negative subscripts to address
array indexes relative to the highest-numbered index. You must use
the subscript expansion, i.e. `"${arr[@]:(-n):1}"`, to expand the
nth-last element (or the next-highest indexed after `n` if `arr[n]`
@ -570,7 +559,7 @@ dynamically calls a function whose name is resolved from the array.
### Bugs
- **Fixed in 4.3** Bash 4.2.\* and earlier considers each chunk of a
- **Fixed in 4.3** Bash 4.2.* and earlier considers each chunk of a
compound assignment, including the subscript for globbing. The
subscript part is considered quoted, but any unquoted glob
characters on the right-hand side of the `[...]=` will be clumped
@ -586,7 +575,7 @@ dynamically calls a function whose name is resolved from the array.
1=a
`
- **Fixed in 4.3** In addition to the above globbing issue,
assignments preceding \"declare\" have an additional effect on brace
assignments preceding "declare" have an additional effect on brace
and pathname expansion. `$ set -x; foo=bar declare arr=( {1..10} )
+ foo=bar
+ declare 'arr=(1)' 'arr=(2)' 'arr=(3)' 'arr=(4)' 'arr=(5)' 'arr=(6)' 'arr=(7)' 'arr=(8)' 'arr=(9)' 'arr=(10)'
@ -687,6 +676,3 @@ to generate these results.
detailed discussion on arrays with many examples.
- [BashSheet - Arrays](http://mywiki.wooledge.org/BashSheet#Arrays) -
Bashsheet quick-reference on Greycat's wiki.
<div hide> vim: set fenc=utf-8 ff=unix ts=4 sts=4 sw=4 ft=dokuwiki et
wrap lbr: </div>

View File

@ -12,7 +12,7 @@ tags:
Bash builds its features on top of a few basic **grammar rules**. The
code you see everywhere, the code you use, is based on those rules.
However, **this is a very theoretical view**, but if you\'re interested,
However, **this is a very theoretical view**, but if you're interested,
it may help you understand why things look the way they look.
If you don't know the commands used in the following examples, just
@ -36,7 +36,7 @@ Every complex Bash operation can be split into simple commands:
ls -l
LC_ALL=C ls
The last one might not be familiar. That one simply adds \"`LC_ALL=C`\"
The last one might not be familiar. That one simply adds "`LC_ALL=C`"
to the environment of the `ls` program. It doesn't affect your current
shell. This also works while calling functions, unless Bash runs in
POSIX(r) mode (in which case it affects your current shell).
@ -46,19 +46,21 @@ can catch it and act on it. Exit code range is from 0 to 255, where 0
means success, and the rest mean either something failed, or there is an
issue to report back to the calling program.
<wrap center round info 90%> The simple command construct is the
**base** for all higher constructs. Everything you execute, from
pipelines to functions, finally ends up in (many) simple commands.
That's why Bash only has one method to [expand and execute a simple
command](../syntax/grammar/parser_exec.md). </wrap>
!!! info "info"
The simple command construct is the
**base** for all higher constructs. Everything you execute, from
pipelines to functions, finally ends up in (many) simple commands.
That's why Bash only has one method to [expand and execute a simple
command](../syntax/grammar/parser_exec.md).
## Pipelines
FIXME Missing an additional article about pipelines and pipelining
!!! warning "FIXME"
Missing an additional article about pipelines and pipelining
`[time [-p]] [ ! ] command [ | command2 ... ]`
**Don't get confused** about the name \"pipeline.\" It's a grammatic
**Don't get confused** about the name "pipeline." It's a grammatic
name for a construct. Such a pipeline isn't necessarily a pair of
commands where stdout/stdin is connected via a real pipe.
@ -73,10 +75,10 @@ count the lines generated by the ls command. The result is the number of
directory entries in /etc.
The last command in the pipeline will set the exit code for the
pipeline. This exit code can be \"inverted\" by prefixing an exclamation
mark to the pipeline: An unsuccessful pipeline will exit \"successful\"
pipeline. This exit code can be "inverted" by prefixing an exclamation
mark to the pipeline: An unsuccessful pipeline will exit "successful"
and vice versa. In this example, the commands in the if stanza will be
executed if the pattern \"\^root:\" is **not** found in `/etc/passwd`:
executed if the pattern "^root:" is **not** found in `/etc/passwd`:
if ! grep '^root:' /etc/passwd; then
echo "No root user defined... eh?"
@ -85,10 +87,10 @@ executed if the pattern \"\^root:\" is **not** found in `/etc/passwd`:
Yes, this is also a pipeline (although there is no pipe!), because the
**exclamation mark to invert the exit code** can only be used in a
pipeline. If `grep`'s exit code is 1 (FALSE) (the text was not found),
the leading `!` will \"invert\" the exit code, and the shell sees (and
the leading `!` will "invert" the exit code, and the shell sees (and
acts on) exit code 0 (TRUE) and the `then` part of the `if` stanza is
executed. One could say we checked for
\"`not grep "^root" /etc/passwd`\".
"`not grep "^root" /etc/passwd`".
The [set option pipefail](../commands/builtin/set.md#attributes) determines
the behavior of how bash reports the exit code of a pipeline. If it's
@ -117,7 +119,8 @@ syntax:
## Lists
FIXME Missing an additional article about list operators
!!! warning "FIXME"
Missing an additional article about list operators
A list is a sequence of one or more [pipelines](#pipelines)
separated by one of the operators `;`, `&`, `&&`, or `││`, and
@ -128,15 +131,15 @@ that all have **different meanings** for Bash.
Your whole Bash script technically is one big single list!
Operator Description
------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
`<PIPELINE1> <newline> <PIPELINE2>` Newlines completely separate pipelines. The next pipeline is executed without any checks. (You enter a command and press `<RETURN>`!)
`<PIPELINE1> ; <PIPELINE2>` The semicolon does what `<newline>` does: It separates the pipelines
`<PIPELINE> & <PIPELINE>` The pipeline in front of the `&` is executed **asynchronously** (\"in the background\"). If a pipeline follows this, it is executed immediately after the async pipeline starts
`<PIPELINE1> && <PIPELINE2>` `<PIPELINE1>` is executed and **only** if its exit code was 0 (TRUE), then `<PIPELINE2>` is executed (AND-List)
`<PIPELINE1> || <PIPELINE2>` `<PIPELINE1>` is executed and **only** if its exit code was **not** 0 (FALSE), then `<PIPELINE2>` is executed (OR-List)
|Operator|Description|
|--------|-----------|
|`<PIPELINE1> <newline> <PIPELINE2>`|Newlines completely separate pipelines. The next pipeline is executed without any checks. (You enter a command and press `<RETURN>`!)|
|`<PIPELINE1> ; <PIPELINE2>`|The semicolon does what `<newline>` does: It separates the pipelines|
|`<PIPELINE> & <PIPELINE>`|The pipeline in front of the `&` is executed **asynchronously** ("in the background"). If a pipeline follows this, it is executed immediately after the async pipeline starts|
|`<PIPELINE1> && <PIPELINE2>`|`<PIPELINE1>` is executed and **only** if its exit code was 0 (TRUE), then `<PIPELINE2>` is executed (AND-List)|
|`<PIPELINE1>||<PIPELINE2>`|`<PIPELINE1>` is executed and **only** if its exit code was **not** 0 (FALSE), then `<PIPELINE2>` is executed (OR-List)|
**Note:** POSIX calls this construct a \"compound lists\".
**Note:** POSIX calls this construct a "compound lists".
## Compound Commands
@ -144,7 +147,7 @@ See also the [list of compound commands](../syntax/ccmd/intro.md).
There are two forms of compound commands:
- form a new syntax element using a list as a \"body\"
- form a new syntax element using a list as a "body"
- completly independant syntax elements
Essentially, everything else that's not described in this article.
@ -157,29 +160,30 @@ Compound commands have the following characteristics:
See the following table for a short overview (no details - just an
overview):
Compound command syntax Description
------------------------------------------------------------ ---------------------------------------------------------------------------------------------------------------------------------------------------------
`( <LIST> )` Execute `<LIST>` in an extra subshell => [article](../syntax/ccmd/grouping_subshell.md)
`{ <LIST> ; }` Execute `<LIST>` as separate group (but not in a subshell) => [article](../syntax/ccmd/grouping_plain.md)
`(( <EXPRESSION> ))` Evaluate the arithmetic expression `<EXPRESSION>` => [article](../syntax/ccmd/arithmetic_eval.md)
`[[ <EXPRESSION> ]]` Evaluate the conditional expression `<EXPRESSION>` (aka \"the new test command\") => [article](../syntax/ccmd/conditional_expression.md)
`for <NAME> in <WORDS> ; do <LIST> ; done` Executes `<LIST>` while setting the variable `<NAME>` to one of `<WORDS>` on every iteration (classic for-loop) => [article](../syntax/ccmd/classic_for.md)
`for (( <EXPR1> ; <EXPR2> ; <EXPR3> )) ; do <LIST> ; done` C-style for-loop (driven by arithmetic expressions) => [article](../syntax/ccmd/c_for.md)
`select <NAME> in <WORDS> ; do <LIST> ; done` Provides simple menus => [article](../syntax/ccmd/user_select.md)
`case <WORD> in <PATTERN>) <LIST> ;; ... esac` Decisions based on pattern matching - executing `<LIST>` on match => [article](../syntax/ccmd/case.md)
`if <LIST> ; then <LIST> ; else <LIST> ; fi` The if clause: makes decisions based on exit codes => [article](../syntax/ccmd/if_clause.md)
`while <LIST1> ; do <LIST2> ; done` Execute `<LIST2>` while `<LIST1>` returns TRUE (exit code) => [article](../syntax/ccmd/while_loop.md)
`until <LIST1> ; do <LIST2> ; done` Execute `<LIST2>` until `<LIST1>` returns TRUE (exit code) => [article](../syntax/ccmd/until_loop.md)
|Compound command syntax|Description|
|-----------------------|-----------|
|`( <LIST> )`|Execute `<LIST>` in an extra subshell =\> [article](../syntax/ccmd/grouping_subshell.md)|
|`{ <LIST> ; }`|Execute `<LIST>` as separate group (but not in a subshell) =\> [article](../syntax/ccmd/grouping_plain.md)|
|`(( <EXPRESSION> ))`|Evaluate the arithmetic expression `<EXPRESSION>` =\> [article](../syntax/ccmd/arithmetic_eval.md)|
|`[[ <EXPRESSION> ]]`|Evaluate the conditional expression `<EXPRESSION>` (aka "the new test command") =\> [article](../syntax/ccmd/conditional_expression.md)|
|`for <NAME> in <WORDS> ; do <LIST> ; done`|Executes `<LIST>` while setting the variable `<NAME>` to one of `<WORDS>` on every iteration (classic for-loop) =\> [article](../syntax/ccmd/classic_for.md)|
|`for (( <EXPR1> ; <EXPR2> ; <EXPR3> )) ; do <LIST> ; done`|C-style for-loop (driven by arithmetic expressions) =\> [article](../syntax/ccmd/c_for.md)|
|`select <NAME> in <WORDS> ; do <LIST> ; done`|Provides simple menus =\> [article](../syntax/ccmd/user_select.md)|
|`case <WORD> in <PATTERN>) <LIST> ;; ... esac`|Decisions based on pattern matching - executing `<LIST>` on match =\> [article](../syntax/ccmd/case.md)|
|`if <LIST> ; then <LIST> ; else <LIST> ; fi`|The if clause: makes decisions based on exit codes =\> [article](../syntax/ccmd/if_clause.md)|
|`while <LIST1> ; do <LIST2> ; done`|Execute `<LIST2>` while `<LIST1>` returns TRUE (exit code) =\> [article](../syntax/ccmd/while_loop.md)|
|`until <LIST1> ; do <LIST2> ; done`|Execute `<LIST2>` until `<LIST1>` returns TRUE (exit code) =\> [article](../syntax/ccmd/until_loop.md)|
## Shell Function Definitions
FIXME Missing an additional article about shell functions
!!! warning "FIXME"
Missing an additional article about shell functions
A shell function definition makes a [compound
command](#compound_commands) available via a new name. When
the function runs, it has its own \"private\" set of positional
the function runs, it has its own "private" set of positional
parameters and I/O descriptors. It acts like a script-within-the-script.
Simply stated: **You\'ve created a new command.**
Simply stated: **You've created a new command.**
The definition is easy (one of many possibilities):
@ -219,7 +223,7 @@ without the space.
I suggest using the first form. It's specified in POSIX and all
Bourne-like shells seem to support it.
[**Note:**]{.underline} Before version `2.05-alpha1`, Bash only
<u>**Note:**</u> Before version `2.05-alpha1`, Bash only
recognized the definition using curly braces (`name() { ... }`), other
shells allow the definition using **any** command (not just the compound
command set).
@ -244,9 +248,9 @@ like this:
**Just informational(1):**
Internally, for forking, Bash stores function definitions in environment
variables. Variables with the content \"*() \....*\".
variables. Variables with the content "*() ....*".
Something similar to the following works without \"officially\"
Something similar to the following works without "officially"
declaring a function:
$ export testfn="() { echo test; }"
@ -267,8 +271,8 @@ The elements of this name aren't subject to a path search.
Weird function names should not be used. Quote from the maintainer:
- * It was a mistake to allow such characters in function names
(\`unset\' doesn't work to unset them without forcing -f, for
instance). We\'re stuck with them for backwards compatibility, but I
(`unset` doesn't work to unset them without forcing `-f`, for
instance). We're stuck with them for backwards compatibility, but I
don't have to encourage their use. *
## Grammar summary
@ -288,15 +292,16 @@ Weird function names should not be used. Quote from the maintainer:
## Examples for classification
FIXME more\...
!!! warning "FIXME"
more...
------------------------------------------------------------------------
[A (very) simple command]{.underline}
<u>A (very) simple command</u>
echo "Hello world..."
[All of the following are simple commands]{.underline}
<u>All of the following are simple commands</u>
x=5
@ -306,7 +311,7 @@ FIXME more\...
------------------------------------------------------------------------
[A common compound command]{.underline}
<u>A common compound command</u>
if [ -d /data/mp3 ]; then
cp mymusic.mp3 /data/mp3

View File

@ -20,10 +20,10 @@
The C-style for-loop is a [compound
command](../../syntax/basicgrammar.md#compound_commands) derived from the
equivalent ksh88 feature, which is in turn derived from the C \"for\"
equivalent ksh88 feature, which is in turn derived from the C "for"
keyword. Its purpose is to provide a convenient way to evaluate
arithmetic expressions in a loop, plus initialize any required
arithmetic variables. It is one of the main \"loop with a counter\"
arithmetic variables. It is one of the main "loop with a counter"
mechanisms available in the language.
The `((;;))` syntax at the top of the loop is not an ordinary
@ -103,7 +103,7 @@ functions and local variables for initialization.</div>
### Simple counter
A simple counter, the loop iterates 101 times (\"0\" to \"100\" are 101
A simple counter, the loop iterates 101 times ("0" to "100" are 101
numbers -> 101 runs!), and everytime the variable `x` is set to the
current value.
@ -111,9 +111,6 @@ current value.
- Before every iteration it **checks** if `x ≤ 100`
- After every iteration it **changes** `x++`
```{=html}
<!-- -->
```
for ((x = 0 ; x <= 100 ; x++)); do
echo "Counter: $x"
done
@ -131,8 +128,8 @@ will count from 0 to 100, but with a **step of 10**.
### Bits analyzer
This example loops through the bit-values of a Byte, beginning from 128,
ending at 1. If that bit is set in the `testbyte`, it prints \"`1`\",
else \"`0`\" => it prints the binary representation of the `testbyte`
ending at 1. If that bit is set in the `testbyte`, it prints "`1`",
else "`0`" => it prints the binary representation of the `testbyte`
value (8 bits).
#!/usr/bin/env bash
@ -161,7 +158,7 @@ value (8 bits).
# vim: set fenc=utf-8 ff=unix ft=sh :
<div hide>
<div hide>
testbyte=123
for (( n = 128 ; n >= 1 ; n /= 2 )); do
@ -173,11 +170,11 @@ value (8 bits).
done
echo
</div>
</div>
Why that one begins at 128 (highest value, on the left) and not 1
(lowest value, on the right)? It's easier to print from left to
right\...
right...
We arrive at 128 for `n` through the recursive arithmetic expression
stored in `x`, which calculates the next-greatest power of 2 after `m`.
@ -186,7 +183,7 @@ it has a built-in feature for `printf` to print a representation of any
number in an arbitrary base (up to 64). Very few languages have that
ability built-in, even things like Python.
### Up, down, up, down\...
### Up, down, up, down...
This counts up and down from `0` to `${1:-5}`, `${2:-4}` times,
demonstrating more complicated arithmetic expressions with multiple
@ -196,7 +193,8 @@ variables.
printf '%*s\n' "$((n+1))" "$n"
done
<code> \~ \$ bash <(xclip -o) 1
``` bash
~ \$ bash <(xclip -o) 1
2
3
@ -216,7 +214,8 @@ variables.
3
2
1 </code>
1
```
## Portability considerations

View File

@ -43,7 +43,7 @@ done**, which means you can leave expansions unquoted without problems:
esac
This is similar to the behavior of the [conditional expression command
(\"new test command\")](../../syntax/ccmd/conditional_expression.md) (also no
("new test command")](../../syntax/ccmd/conditional_expression.md) (also no
word splitting for expansions).
Unlike the C-case-statement, only the matching list and nothing else is
@ -55,13 +55,13 @@ This is a POSIX-compatable equivalent to the `@(pattern-list)` extglob
construct.
The `case` statement is one of the most difficult commands to indent
clearly, and people frequently ask about the most \"correct\" style.
clearly, and people frequently ask about the most "correct" style.
Just do your best - there are many variations of indenting style for
`case` and no real agreed-upon best practice.
## Examples
Another one of my stupid examples\...
Another one of my stupid examples...
printf '%s ' 'Which fruit do you like most?'
read -${BASH_VERSION+e}r fruit

View File

@ -23,7 +23,7 @@ alternative, historical and undocumented syntax [^1]
## Description
For every word in `<WORDS>`, one iteration of the loop is performed and
the variable `<NAME>` is set to the current word. If no \"`in <WORDS>`\"
the variable `<NAME>` is set to the current word. If no "`in <WORDS>`"
is present to give an own word-list, then the positional parameters
(`"$@"`) are used (the arguments to the script or function). In this
case (and only in this case), the semicolon between the variable name
@ -60,14 +60,14 @@ specified by POSIX(r).
The return status is the one of the last command executed in `<LIST>` or
`0` (`TRUE`), if the item list `<WORDS>` evaluates to nothing (i.e.:
\"is empty\"!).
"is empty"!).
## Examples
### Iterate over array elements
With some array syntax (see [arrays](../../syntax/arrays.md)) you can easily
\"feed\" the for-loop to iterate over all elements in an array (by
"feed" the for-loop to iterate over all elements in an array (by
mass-expanding all elements):
``` bash
@ -156,7 +156,7 @@ done
### Loop over a number range
Beginning in Bash 4, you can also use \"sequence expression\" form of
Beginning in Bash 4, you can also use "sequence expression" form of
[brace expansion](../../syntax/expansion/brace.md) syntax when looping over
numbers, and this form does not create leading zeroes unless you ask for
them:

View File

@ -16,28 +16,17 @@ The testing features basically are the same (see the lists for [classic
test command](../../commands/classictest.md)), with some additions and
extensions.
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Operator Description
-------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------
`( <EXPRESSION> )` Used to group expressions, to influence precedence of operators
`<EXPRESSION1> && <EXPRESSION2>` `TRUE` if `<EXPRESSION1>`**and**`<EXPRESSION2>` are `TRUE` (do **not** use `-a`!)
`<EXPRESSION1> || <EXPRESSION2>` `TRUE` if `<EXPRESSION1>`**or**`<EXPRESSION2>` is `TRUE` (do **not** use `-o`!)
`<STRING> == <PATTERN>` `<STRING>` is checked against the pattern `<PATTERN>` - `TRUE` on a match\
*But note¹, quoting the pattern forces a literal comparison.*
`<STRING> = <PATTERN>` equivalent to the `==` operator
`<STRING> != <PATTERN>` `<STRING>` is checked against the pattern `<PATTERN>` - `TRUE` on **no match**
`<STRING> =~ <ERE>` `<STRING>` is checked against the [extended regular expression](https://en.wikipedia.org/wiki/Regular_expression#POSIX_extended) `<ERE>` - `TRUE` on a match
See the [classic test operators](../../commands/classictest.md#file_tests) Do **not** use the `test`-typical operators `-a` and `-o` for AND and OR.
See also [arithmetic comparisons](../../syntax/arith_expr.md#comparisons) Using `(( <EXPRESSION> ))`, the [arithmetic expression compound command](../../syntax/ccmd/arithmetic_eval.md)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|Operator|Description|
|--|--|
|`( <EXPRESSION> )`|Used to group expressions, to influence precedence of operators|
|`<EXPRESSION1> && <EXPRESSION2>`|`TRUE` if `<EXPRESSION1>`**and**`<EXPRESSION2>` are `TRUE` (do **not** use `-a`!)|
|`<EXPRESSION1>||<EXPRESSION2>`|`TRUE` if `<EXPRESSION1>`**or**`<EXPRESSION2>` is `TRUE` (do **not** use `-o`!)|
|`<STRING> == <PATTERN>`|`<STRING>` is checked against the pattern `<PATTERN>` - `TRUE` on a match<br>*But note¹, quoting the pattern forces a literal comparison.*|
|`<STRING> = <PATTERN>`|equivalent to the `==` operator|
|`<STRING> != <PATTERN>`|`<STRING>` is checked against the pattern `<PATTERN>` - `TRUE` on **no match**|
|`<STRING> =~ <ERE>`|`<STRING>` is checked against the [extended regular expression](https://en.wikipedia.org/wiki/Regular_expression#POSIX_extended) `<ERE>` - `TRUE` on a match|
|See the [classic test operators](../../commands/classictest.md#file_tests)|Do **not** use the `test`-typical operators `-a` and `-o` for AND and OR.|
|See also [arithmetic comparisons](../../syntax/arith_expr.md#comparisons)|Using `(( <EXPRESSION> ))`, the [arithmetic expression compound command](../../syntax/ccmd/arithmetic_eval.md)|
When the `==` and `!=` operators are used, the string to the right of
the operator is considered a pattern and matched according to the rules
@ -50,7 +39,7 @@ literal string.
When the operators `<` and `>` are used (string collation order), the
test happens using the current locale when the `compat` level is greater
than \"40\".
than "40".
Operator precedence (highest => lowest):
@ -151,7 +140,7 @@ Example:
### Behaviour differences compared to the builtin test command
As of Bash 4.1 alpha, the test primaries \'<\' and \'>\' (compare
As of Bash 4.1 alpha, the test primaries '&lt;' and '&gt;' (compare
strings lexicographically) use the current locale settings, while the
same primitives for the builtin test command don't. This leads to the
following situation where they behave differently:
@ -180,7 +169,7 @@ both contains whitespace and is not the result of an expansion.
- `[[ ... ]]` functionality isn't specified by POSIX(R), though it's
a reserved word
- Amongst the major \"POSIX-shell superset languages\" (for lack of a
- Amongst the major "POSIX-shell superset languages" (for lack of a
better term) which do have `[[`, the test expression compound
command is one of the very most portable non-POSIX features. Aside
from the `=~` operator, almost every major feature is consistent

View File

@ -13,7 +13,7 @@
The [list](../../syntax/basicgrammar.md#lists) `<LIST>` is simply executed in
the **current** shell environment. The list must be terminated with a
**newline** or **semicolon**. For parsing reasons, the curly braces must
be separated from `<LIST>` by a **semicolon** and **blanks** if they\'re
be separated from `<LIST>` by a **semicolon** and **blanks** if they're
in the same line! [^1][^2]
This is known as a **group command**. The return status is the [exit

View File

@ -8,7 +8,7 @@
The [list](../../syntax/basicgrammar.md#lists) `<LIST>` is executed in a
separate shell - a subprocess. No changes to the environment (variables
etc\...) are reflected in the \"main shell\".
etc...) are reflected in the "main shell".
## Examples

View File

@ -1,10 +1,10 @@
# Bash compound commands
The main part of Bash's syntax are the so-called **compound commands**.
They\'re called like that because they use \"real\" commands ([simple
They're called like that because they use "real" commands ([simple
commands](../../syntax/basicgrammar.md#simple_commands) or
[lists](../../syntax/basicgrammar.md#lists)) and knit some intelligence around
them. That is what the essential \"Bash language\" is made of.
them. That is what the essential "Bash language" is made of.
## Command grouping
@ -17,7 +17,7 @@ Note that conditionals can also be scripted using
[list](../../syntax/basicgrammar.md#lists), which are syntax elements, not
commands.
- the \"new\" test command: [conditional
- the "new" test command: [conditional
expression](conditional_expression.md)
- if-clause: [conditional branching](if_clause.md)
- case statement: [pattern-based branching](case.md)

View File

@ -53,8 +53,8 @@ expansion is to be assigned to an array, another method is possible
using [declaration commands](../../commands/builtin/declare.md):
`declare -a 'pics=(img{'"$a..$b"'}.png)'; mv "${pics[@]}" ../imgs` This
is significantly safer, but one must still be careful to control the
values of \$a and \$b. Both the exact quoting, and explicitly including
\"-a\" are important.
values of `$a` and `$b`. Both the exact quoting, and explicitly including
"`-a`" are important.
The brace expansion is present in two basic forms, **string lists** and
**ranges**.
@ -87,24 +87,21 @@ With prefix or suffix strings, the result is a space-separated list of
_I- _want- _my- _money- _back-
The brace expansion is only performed, if the given string list is
really a **list of strings**, i.e., if there is a minimum of one \"`,`\"
really a **list of strings**, i.e., if there is a minimum of one "`,`"
(comma)! Something like `{money}` doesn't expand to something special,
it's really only the text \"`{money}`\".
it's really only the text "`{money}`".
## Ranges
{<START>..<END>}
Brace expansion using ranges is written giving the startpoint and the
endpoint of the range. This is a \"sequence expression\". The sequences
endpoint of the range. This is a "sequence expression". The sequences
can be of two types
- integers (optionally zero padded, optionally with a given increment)
- characters
```{=html}
<!-- -->
```
$ echo {5..12}
5 6 7 8 9 10 11 12
@ -186,13 +183,10 @@ for.
mkdir /home/bash/test/{foo,bar,baz,cat,dog}
### Generate numbers with a prefix 001 002 \...
### Generate numbers with a prefix 001 002 ...
- Using a prefix:
```{=html}
<!-- -->
```
for i in 0{1..9} 10; do printf "%s\n" "$i";done
If you need to create words with the number embedded, you can use nested
@ -202,9 +196,6 @@ brace:
- Formatting the numbers with printf:
```{=html}
<!-- -->
```
echo $(printf "img%02d.png " {1..99})
See the [text below](#news_in_bash_4.0) for a new Bash 4 method.
@ -217,34 +208,33 @@ Can be written as
somecommand -v{,,,,}
\...which is a kind of a hack, but hey, it works.
...which is a kind of a hack, but hey, it works.
<div round info>
#### More fun
The most optimal possible brace expansion to expand n arguments of
course consists of n's prime factors. We can use the \"factor\" program
bundled with GNU coreutils to emit a brace expansion that will expand
any number of arguments.
!!! info "More fun"
function braceify {
[[ $1 == +([[:digit:]]) ]] || return
typeset -a a
read -ra a < <(factor "$1")
eval "echo $(printf '{$(printf ,%%.s {1..%s})}' "${a[@]:1}")"
}
The most optimal possible brace expansion to expand n arguments of
course consists of n's prime factors. We can use the "factor" program
bundled with GNU coreutils to emit a brace expansion that will expand
any number of arguments.
printf 'eval printf "$arg"%s' "$(braceify 1000000)"
function braceify {
[[ $1 == +([[:digit:]]) ]] || return
typeset -a a
read -ra a < <(factor "$1")
eval "echo $(printf '{$(printf ,%%.s {1..%s})}' "${a[@]:1}")"
}
\"Braceify\" generates the expansion code itself. In this example we
inject that output into a template which displays the most terse brace
expansion code that would expand `"$arg"` 1,000,000 times if evaluated.
In this case, the output is:
printf 'eval printf "$arg"%s' "$(braceify 1000000)"
eval printf "$arg"{,,}{,,}{,,}{,,}{,,}{,,}{,,,,,}{,,,,,}{,,,,,}{,,,,,}{,,,,,}{,,,,,}
"Braceify" generates the expansion code itself. In this example we
inject that output into a template which displays the most terse brace
expansion code that would expand `"$arg"` 1,000,000 times if evaluated.
In this case, the output is:
eval printf "$arg"{,,}{,,}{,,}{,,}{,,}{,,}{,,,,,}{,,,,,}{,,,,,}{,,,,,}{,,,,,}{,,,,,}
</div>
## New in Bash 4.0

View File

@ -33,12 +33,12 @@ In later steps, **if not quoted**, the results undergo [word
splitting](../../syntax/expansion/wordsplit.md) and [pathname
expansion](../../syntax/expansion/globs.md). You have to remember that, because
the word splitting will also remove embedded newlines and other `IFS`
characters and break the results up into several words. Also you\'ll
characters and break the results up into several words. Also you'll
probably get unexpected pathname matches. **If you need the literal
results, quote the command substitution!**
The second form `` `COMMAND` `` is more or less obsolete for Bash, since
it has some trouble with nesting (\"inner\" backticks need to be
it has some trouble with nesting ("inner" backticks need to be
escaped) and escaping characters. Use `$(COMMAND)`, it's also POSIX!
When you [call an explicit subshell](../../syntax/ccmd/grouping_subshell.md)
@ -72,17 +72,17 @@ escaping-neutral, it's nestable, it's also POSIX. But take a look at
the following code snips to decide yourself which form you need under
specific circumstances:
**[Nesting]{.underline}**
**<u>Nesting</u>**
Backtick form `` `...` `` is not directly nestable. You will have to
escape the \"inner\" backticks. Also, the deeper you go, the more escape
escape the "inner" backticks. Also, the deeper you go, the more escape
characters you need. Ugly.
echo `echo `ls`` # INCORRECT
echo `echo \`ls\`` # CORRECT
echo $(echo $(ls)) # CORRECT
**[Parsing]{.underline}**
**<u>Parsing</u>**
All is based on the fact that the backquote-form is simple character
substitution, while every `$()`-construct opens an own, subsequent
@ -91,21 +91,21 @@ normal on a commandline. No special escaping of **nothing** is needed:
echo "$(echo "$(ls)")" # nested double-quotes - no problem
**[Constructs you should avoid]{.underline}**
**<u>Constructs you should avoid</u>**
It's not all shiny with `$()`, at least for my current Bash
(`3.1.17(1)-release`. :!: [**Update:** Fixed since `3.2-beta` together
with a misinterpretion of \'))\' being recognized as arithmetic
expansion \[by redduck666\]]{.underline}). This command seems to
incorrectly close the substitution step and echo prints \"ls\" and
\")\":
(`3.1.17(1)-release`. :!: <u>**Update:** Fixed since `3.2-beta` together
with a misinterpretion of '))' being recognized as arithmetic
expansion by redduck666</u>). This command seems to
incorrectly close the substitution step and echo prints "ls" and
")":
echo $(
# some comment ending with a )
ls
)
It seems that every closing \")\" confuses this construct. Also a (very
It seems that every closing ")" confuses this construct. Also a (very
uncommon ;-)) construct like:
echo $(read VAR; case "$var" in foo) blah ;; esac) # spits out some error, when it sees the ";;"
@ -113,7 +113,7 @@ uncommon ;-)) construct like:
# fixes it:
echo $(read VAR; case "$var" in (foo) blah ;; esac) # will work, but just let it be, please ;-)
**[Conclusion:]{.underline}**
**<u>Conclusion:</u>**
In general, the `$()` should be the preferred method:
@ -141,11 +141,11 @@ target, because command substitution only catches `STDOUT`!
var=$(echo -n $'\n'); echo -n "$var"; # $var == ""
var=$(echo -n $'\n'; echo -n x); var="${var%x}"; echo -n "$var" # $var == "\n"
This adds \"x\" to the output, which prevents the trailing newlines of
the previous commands\' output from being deleted by \$().
This adds "x" to the output, which prevents the trailing newlines of
the previous commands' output from being deleted by `$()`.
By removing this \"x\" later on, we are left with the previous
commands\' output with its trailing newlines.
By removing this "x" later on, we are left with the previous
commands' output with its trailing newlines.
## See also

View File

@ -3,8 +3,8 @@
## General
Unlike on other platforms you may have seen, on UNIX(r), the shell is
responsible for interpreting and expanding globs (\"filename
wildcards\"). A called program will never see the glob itself; it will
responsible for interpreting and expanding globs ("filename
wildcards"). A called program will never see the glob itself; it will
only see the expanded filenames as its arguments (here, all filenames
matching `*.log`):
@ -43,7 +43,7 @@ other `IFS`-characters they contain.
corrections when matching directory names
- when the shell option `globstar` is set, the glob `**` will
recursively match all files and directories. This glob isn't
\"configurable\", i.e. you **can't** do something like `**.c` to
"configurable", i.e. you **can't** do something like `**.c` to
recursively get all `*.c` filenames.
- when the shell option `globasciiranges` is set, the bracket-range
globs (e.g. `[A-Z]`) use C locale order rather than the configured
@ -56,7 +56,7 @@ other `IFS`-characters they contain.
### nullglob
Normally, when no glob specified matches an existing filename, no
pathname expansion is performed, and the globs are [**not**]{.underline}
pathname expansion is performed, and the globs are <u>**not**</u>
removed:
$ echo "Textfiles here:" *.txt
@ -75,7 +75,7 @@ This can be very annoying, for example when you drive a
done
When no file name matches the glob, the loop will not only output stupid
text (\"`BEGIN: *.txt`\"), but also will make the `cat`-command fail
text ("`BEGIN: *.txt`"), but also will make the `cat`-command fail
with an error, since no file named `*.txt` exists.
Now, when the shell option `nullglob` is set, Bash will remove the
@ -92,11 +92,11 @@ and the glob is gone.
### Glob characters
- \* - means \'match any number of characters\'. \'/\' is not matched
- `*` - means \'match any number of characters\'. \'/\' is not matched
(and depending on your settings, things like \'.\' may or may not be
matched, see above)
- ? - means \'match any single character\'
- \[abc\] - match any of the characters listed. This syntax also
- `?` - means \'match any single character\'
- `[abc]` - match any of the characters listed. This syntax also
supports ranges, like \[0-9\]
For example, to match something beginning with either \'S\' or \'K\'

View File

@ -28,7 +28,7 @@ The most simple example of this behaviour is a referenced variable:
The `echo` program definitely doesn't care about what a shell variable
is. It is Bash's job to deal with the variable. Bash **expands** the
string \"`$mystring`\" to \"`Hello world`\", so that `echo` will only
string "`$mystring`" to "`Hello world`", so that `echo` will only
see `Hello world`, not the variable or anything else!
After all these expansions and substitutions are done, all quotes that

View File

@ -42,21 +42,22 @@ from a file).
### Scope
<note important> Note: According to multiple comments and sources, the
scope of process substitution file descriptors is **not** stable,
guaranteed, or specified by bash. Newer versions of bash (5.0+) seem to
have shorter scope, and substitutions scope seems to be shorter than
function scope. See
[stackexchange](https://unix.stackexchange.com/questions/425456/conditional-process-substitution)
and
[stackoverflow](https://stackoverflow.com/questions/46660020/bash-what-is-the-scope-of-the-process-substitution);
the latter discussion contains a script that can test the scoping
behavior case-by-case </note>
!!! note "Note"
According to multiple comments and sources, the
scope of process substitution file descriptors is **not** stable,
guaranteed, or specified by bash. Newer versions of bash (5.0+) seem to
have shorter scope, and substitutions scope seems to be shorter than
function scope. See
[stackexchange](https://unix.stackexchange.com/questions/425456/conditional-process-substitution)
and
[stackoverflow](https://stackoverflow.com/questions/46660020/bash-what-is-the-scope-of-the-process-substitution);
the latter discussion contains a script that can test the scoping
behavior case-by-case
If a process substitution is expanded as an argument to a function,
expanded to an environment variable during calling of a function, or
expanded to any assignment within a function, the process substitution
will be \"held open\" for use by any command within the function or its
will be "held open" for use by any command within the function or its
callees, until the function in which it was set returns. If the same
variable is set again within a callee, unless the new variable is local,
the previous process substitution is closed and will be unavailable to
@ -97,10 +98,11 @@ where those files are written to and destroyed automatically.
### Avoiding subshells
<WRAP center round info 60%> See Also:
[BashFAQ/024](http://mywiki.wooledge.org/BashFAQ/024) -- *I set
variables in a loop that's in a pipeline. Why do they disappear after
the loop terminates? Or, why can't I pipe data to read?* </WRAP>
!!! info "See Also"
See Also:
[BashFAQ/024](http://mywiki.wooledge.org/BashFAQ/024) -- *I set
variables in a loop that's in a pipeline. Why do they disappear after
the loop terminates? Or, why can't I pipe data to read?*
One of the most common uses for process substitutions is to avoid the
final subshell that results from executing a pipeline. The following is
@ -120,7 +122,7 @@ Due to the pipe, the `while read; do ... done` part is executed in a
subshell (in Bash, by default), which means `counter` is only
incremented within the subshell. When the pipeline finishes, the
subshell is terminated, and the `counter` visible to `echo` is still at
\"0\"!
"0"!
Process substitution helps us avoid the pipe operator (the reason for
the subshell):
@ -149,7 +151,7 @@ note that the space is required in order to disambiguate the syntax from
### Process substitution assigned to a parameter
This example demonstrates how process substitutions can be made to
resemble \"passable\" objects. This results in converting the output of
resemble "passable" objects. This results in converting the output of
`f`'s argument to uppercase.
``` bash

View File

@ -44,24 +44,25 @@ Tilde expansion is also performed everytime a variable is assigned:
- after **every** `:` (colon) in the assigned value:
`TARGET=file:~moonman/share`
<note info> As of now (Bash 4.3-alpha) the following constructs
**also** works, though it's not a variable assignment:
!!! info "Note"
As of now (Bash 4.3-alpha) the following constructs
**also** works, though it's not a variable assignment:
echo foo=~
echo foo=:~
echo foo=~
echo foo=:~
I don't know yet, if this is a bug or intended. </note>
I don't know yet, if this is a bug or intended.
This way you can correctly use the tilde expansion in your
[PATH](../../syntax/shellvars.md#PATH):
PATH=~/mybins:~peter/mybins:$PATH
**Spaces in the referenced pathes?** A construct like\...
**Spaces in the referenced pathes?** A construct like...
~/"my directory"
\...is perfectly valid and works!
...is perfectly valid and works!
## Home directory
@ -84,7 +85,7 @@ precedence:
- expand to the home directory of the user executing the shell
(operating system)
That means, the variable `HOME` can override the \"real\" home
That means, the variable `HOME` can override the "real" home
directory, at least regarding tilde expansion.
## Current working directory

View File

@ -1,6 +1,7 @@
# Word splitting
FIXME to be continued!
!!! warning "FIXME"
to be continued!
Word splitting occurs once any of the following expansions are done (and
only then!)
@ -18,9 +19,9 @@ are **not double-quoted**!
The `IFS` variable holds the characters that Bash sees as word
boundaries in this step. The default contains the characters
- <space>
- <tab>
- <newline>
- &lt;space&gt;
- &lt;tab&gt;
- &lt;newline&gt;
These characters are also assumed when IFS is **unset**. When `IFS` is
**empty** (nullstring), no word splitting is performed at all.
@ -34,10 +35,10 @@ the expansion result is split at these positions into multiple words.
This doesn't happen when the expansion results were **double-quoted**.
When a null-string (e.g., something that before expanded to
>>nothing<<) is found, it is removed, unless it is quoted (`''` or
&gt;&gt;nothing&lt;&lt;) is found, it is removed, unless it is quoted (`''` or
`""`).
[**Again note:**]{.underline} Without any expansion beforehand, Bash
<u>**Again note:**</u> Without any expansion beforehand, Bash
won't perform word splitting! In this case, the initial token parsing
is solely responsible.

View File

@ -10,22 +10,22 @@ tags:
- execution
---
FIXME work in progress\...
!!! warning "FIXME"
work in progress...
# Parsing and execution
Nearly everything in [Bash grammar](../../syntax/basicgrammar.md) can be broken
down to a \"simple command\". The only thing Bash has to expand,
down to a "simple command". The only thing Bash has to expand,
evaluate and execute is the simple command.
## Simple command expansion
<div center round info 60%>
!!! info "info"
- <http://lists.gnu.org/archive/html/bug-bash/2013-01/msg00040.html>
- <http://lists.research.att.com/pipermail/ast-developers/2013q2/002456.html>
- <http://lists.gnu.org/archive/html/bug-bash/2013-01/msg00040.html>
- <http://lists.research.att.com/pipermail/ast-developers/2013q2/002456.html>
</div>
This step happens after the initial command line splitting.
@ -82,7 +82,7 @@ The behavior regarding the variable assignment errors can be tested:
<div center round info
60%><http://lists.gnu.org/archive/html/bug-bash/2013-01/msg00054.html></div>
**[This one exits the script completely]{.underline}**
**<u>This one exits the script completely</u>**
#!/bin/sh
# This shell runs in POSIX mode!
@ -95,8 +95,8 @@ The behavior regarding the variable assignment errors can be tested:
echo POST
**[This one terminates only the enclosing compound command (the
`{ ...; }`):]{.underline}**
<u>**This one terminates only the enclosing compound command (the
`{ ...; }`):**</u>
#!/bin/bash
# This shell runs in native Bash-mode!
@ -126,7 +126,8 @@ or install software packages etc. Since this function runs in a separate
execution environment, you can't really influence the main shell with
it (changing directory, setting variables).
FIXME to be continued
!!! warning "FIXME"
to be continued
## See also

View File

@ -108,7 +108,7 @@ more information on buffering issues.
#### background processes
A coprocess\' file descriptors are accessible only to the process from
A coprocess' file descriptors are accessible only to the process from
which the `coproc` was started. They are not inherited by subshells.
Here is a not-so-meaningful illustration. Suppose we want to
@ -222,7 +222,7 @@ exec >&${tee[1]} 2>&1
### Other shells
ksh93, mksh, zsh, and Bash all support something called \"coprocesses\"
ksh93, mksh, zsh, and Bash all support something called "coprocesses"
which all do approximately the same thing. ksh93 and mksh have virtually
identical syntax and semantics for coprocs. A *list* operator: `|&` is
added to the language which runs the preceding *pipeline* as a coprocess
@ -258,7 +258,7 @@ more. See
more details
The ability to use multiple coprocesses in Bash is considered
\"experimental\". Bash will throw an error if you attempt to start more
"experimental". Bash will throw an error if you attempt to start more
than one. This may be overridden at compile-time with the
`MULTIPLE_COPROCS` option. However, at this time there are still issues
-- see the above mailing list discussion.

View File

@ -26,7 +26,7 @@ A pattern is a **string description**. Bash uses them in various ways:
The pattern description language is relatively easy. Any character
that's not mentioned below matches itself. The `NUL` character may not
occur in a pattern. If special characters are quoted, they\'re matched
occur in a pattern. If special characters are quoted, they're matched
literally, i.e., without their special meaning.
Do **not** confuse patterns with ***regular expressions***, because they
@ -34,30 +34,30 @@ share some symbols and do similar matching work.
## Normal pattern language
Sequence Description
---------- ----------------------------------------------------------------------------------------------------------------
`*` Matches **any string**, including the null string (empty string)
`?` Matches any **single character**
`X` Matches the character `X` which can be any character that has no special meaning
`\X` Matches the character `X`, where the character's special meaning is stripped by the backslash
`\\` Matches a backslash
`[...]` Defines a pattern **bracket expression** (see below). Matches any of the enclosed characters at this position.
|Sequence|Description|
|--------|-----------|
|`*`|Matches **any string**, including the null string (empty string)|
|`?`|Matches any **single character**|
|`X`|Matches the character `X` which can be any character that has no special meaning|
|`\X`|Matches the character `X`, where the character's special meaning is stripped by the backslash|
|`\\`|Matches a backslash|
|`[...]`|Defines a pattern **bracket expression** (see below). Matches any of the enclosed characters at this position.|
### Bracket expressions
The bracket expression `[...]` mentioned above has some useful
applications:
Bracket expression Description
---------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
`[XYZ]` The \"normal\" bracket expression, matching either `X`, `Y` or `Z`
`[X-Z]` A range expression: Matching all the characters from `X` to `Y` (your current **locale**, defines how the characters are **sorted**!)
`[[:class:]]` Matches all the characters defined by a [POSIX(r) character class](https://pubs.opengroup.org/onlinepubs/009696899/basedefs/xbd_chap07.html#tag_07_03_01): `alnum`, `alpha`, `ascii`, `blank`, `cntrl`, `digit`, `graph`, `lower`, `print`, `punct`, `space`, `upper`, `word` and `xdigit`
`[^...]` A negating expression: It matches all the characters that are **not** in the bracket expression
`[!...]` Equivalent to `[^...]`
`[]...]` or `[-...]` Used to include the characters `]` and `-` into the set, they need to be the first characters after the opening bracket
`[=C=]` Matches any character that is eqivalent to the collation weight of `C` (current locale!)
`[[.SYMBOL.]]` Matches the collating symbol `SYMBOL`
|Bracket expression|Description|
|------------------|-----------|
|`[XYZ]`|The "normal" bracket expression, matching either `X`, `Y` or `Z`|
|`[X-Z]`|A range expression: Matching all the characters from `X` to `Y` (your current **locale**, defines how the characters are **sorted**!)|
|`[[:class:]]`|Matches all the characters defined by a [POSIX(r) character class](https://pubs.opengroup.org/onlinepubs/009696899/basedefs/xbd_chap07.html#tag_07_03_01): `alnum`, `alpha`, `ascii`, `blank`, `cntrl`, `digit`, `graph`, `lower`, `print`, `punct`, `space`, `upper`, `word` and `xdigit`|
|`[^...]`|A negating expression: It matches all the characters that are **not** in the bracket expression|
|`[!...]`|Equivalent to `[^...]`|
|`[]...]` or `[-...]`|Used to include the characters `]` and `-` into the set, they need to be the first characters after the opening bracket|
|`[=C=]`|Matches any character that is eqivalent to the collation weight of `C` (current locale!)|
|`[[.SYMBOL.]]`|Matches the collating symbol `SYMBOL`|
### Examples
@ -66,23 +66,23 @@ Some simple examples using normal pattern matching:
- Pattern `"Hello world"` matches
- `Hello world`
- Pattern `[Hh]"ello world"` matches
- => `Hello world`
- => `hello world`
- =&gt; `Hello world`
- =&gt; `hello world`
- Pattern `Hello*` matches (for example)
- => `Hello world`
- => `Helloworld`
- => `HelloWoRlD`
- => `Hello`
- =&gt; `Hello world`
- =&gt; `Helloworld`
- =&gt; `HelloWoRlD`
- =&gt; `Hello`
- Pattern `Hello world[[:punct:]]` matches (for example)
- => `Hello world!`
- => `Hello world.`
- => `Hello world+`
- => `Hello world?`
- =&gt; `Hello world!`
- =&gt; `Hello world.`
- =&gt; `Hello world+`
- =&gt; `Hello world?`
- Pattern
`[[.backslash.]]Hello[[.vertical-line.]]world[[.exclamation-mark.]]`
matches (using [collation
symbols](https://pubs.opengroup.org/onlinepubs/009696899/basedefs/xbd_chap07.html#tag_07_03_02_04))
- => `\Hello|world!`
- =&gt; `\Hello|world!`
## Extended pattern language
@ -90,17 +90,17 @@ If you set the [shell option](../internals/shell_options.md) `extglob`, Bash
understands some powerful patterns. A `<PATTERN-LIST>` is one or more
patterns, separated by the pipe-symbol (`PATTERN|PATTERN`).
--------------------- ------------------------------------------------------------
`?(<PATTERN-LIST>)` Matches **zero or one** occurrence of the given patterns
`*(<PATTERN-LIST>)` Matches **zero or more** occurrences of the given patterns
`+(<PATTERN-LIST>)` Matches **one or more** occurrences of the given patterns
`@(<PATTERN-LIST>)` Matches **one** of the given patterns
`!(<PATTERN-LIST>)` Matches anything **except** one of the given patterns
--------------------- ------------------------------------------------------------
|Extended pattern|Matches|
|----------------|-------|
|`?(<PATTERN-LIST>)`|Matches **zero or one** occurrence of the given patterns|
|`*(<PATTERN-LIST>)`|Matches **zero or more** occurrences of the given patterns|
|`+(<PATTERN-LIST>)`|Matches **one or more** occurrences of the given patterns|
|`@(<PATTERN-LIST>)`|Matches **one** of the given patterns|
|`!(<PATTERN-LIST>)`|Matches anything **except** one of the given patterns|
### Examples
**[Delete all but one specific file]{.underline}**
<u>**Delete all but one specific file**</u>
rm -f !(survivior.txt)
@ -108,15 +108,15 @@ patterns, separated by the pipe-symbol (`PATTERN|PATTERN`).
### Related shell options
option classification description
------------------- ------------------------------------- -------------------------------------------------------------------------------
`dotglob` [globbing](../syntax/expansion/globs.md) see [Pathname expansion customization](../syntax/expansion/globs.md#Customization)
`extglob` global enable/disable extended pattern matching language, as described above
`failglob` [globbing](../syntax/expansion/globs.md) see [Pathname expansion customization](../syntax/expansion/globs.md#Customization)
`nocaseglob` [globbing](../syntax/expansion/globs.md) see [Pathname expansion customization](../syntax/expansion/globs.md#Customization)
`nocasematch` pattern/string matching perform pattern matching without regarding the case of individual letters
`nullglob` [globbing](../syntax/expansion/globs.md) see [Pathname expansion customization](../syntax/expansion/globs.md#Customization)
`globasciiranges` [globbing](../syntax/expansion/globs.md) see [Pathname expansion customization](../syntax/expansion/globs.md#Customization)
|option|classification|description|
|------|--------------|-----------|
|`dotglob`|[globbing](../syntax/expansion/globs.md)|see [Pathname expansion customization](/syntax/expansion/globs.md#Customization)|
|`extglob`|global|enable/disable extended pattern matching language, as described above|
|`failglob`|[globbing](../syntax/expansion/globs.md)|see [Pathname expansion customization](/syntax/expansion/globs.md#Customization)|
|`nocaseglob`|[globbing](../syntax/expansion/globs.md)|see [Pathname expansion customization](/syntax/expansion/globs.md#Customization)|
|`nocasematch`|pattern/string matching|perform pattern matching without regarding the case of individual letters|
|`nullglob`|[globbing](../syntax/expansion/globs.md)|see [Pathname expansion customization](/syntax/expansion/globs.md#Customization)|
|`globasciiranges`|[globbing](../syntax/expansion/globs.md)|see [Pathname expansion customization](/syntax/expansion/globs.md#Customization)|
## Bugs and Portability considerations
@ -152,12 +152,12 @@ to those described above.
\* ksh93 supports arbitrary quantifiers just like ERE using the
`{from,to}(pattern-list)` syntax. `{2,4}(foo)bar` matches between 2-4
\"foo\"'s followed by \"bar\". `{2,}(foo)bar` matches 2 or more
\"foo\"'s followed by \"bar\". You can probably figure out the rest. So
"foo"'s followed by "bar". `{2,}(foo)bar` matches 2 or more
"foo"'s followed by "bar". You can probably figure out the rest. So
far, none of the other shells support this syntax.
\* In ksh93, a `pattern-list` may be delimited by either `&` or `|`. `&`
means \"all patterns must be matched\" instead of \"any pattern\". For
means "all patterns must be matched" instead of "any pattern". For
example, `[[ fo0bar == @(fo[0-9]&+([[:alnum:]]))bar ]]` would be true
while `[[ f00bar == @(fo[0-9]&+([[:alnum:]]))bar ]]` is false, because
all members of the and-list must be satisfied. No other shell supports

View File

@ -46,7 +46,7 @@ applicable description mentions arrays below. Please also see the
[article about arrays](../syntax/arrays.md).
For a more technical view what a parameter is and which types exist,
[see the dictionary entry for \"parameter\"](../dict/parameter.md).
[see the dictionary entry for "parameter"](../dict/parameter.md).
## Overview
@ -107,16 +107,16 @@ is identical to using `$FOO` like you see it everywhere, but has the
advantage that it can be immediately followed by characters that would
be interpreted as part of the parameter name otherwise. Compare these
two expressions (`WORD="car"` for example), where we want to print a
word with a trailing \"s\":
word with a trailing "s":
echo "The plural of $WORD is most likely $WORDs"
echo "The plural of $WORD is most likely ${WORD}s"
[Why does the first one fail?]{.underline} It prints nothing, because a
parameter (variable) named \"`WORDs`\" is undefined and thus printed as
\"\" (*nothing*). Without using braces for parameter expansion, Bash
<u>Why does the first one fail?</u> It prints nothing, because a
parameter (variable) named "`WORDs`" is undefined and thus printed as
"" (*nothing*). Without using braces for parameter expansion, Bash
will interpret the sequence of all valid characters from the introducing
\"`$`\" up to the last valid character as name of the parameter. When
"`$`" up to the last valid character as name of the parameter. When
using braces you just force Bash to **only interpret the name inside
your braces**.
@ -138,9 +138,9 @@ individual indexes or mass arguments. An individual index behaves like a
normal parameter, for the mass expansion, please read the article about
arrays linked above.
- \${array\[5\]}
- \${array\[\*\]}
- \${array\[@\]}
- `${array[5]}`
- `${array[*]}`
- `${array[@]}`
## Indirection
@ -158,7 +158,7 @@ you can instead use the form
to enter a level of indirection. The referenced parameter is not
`PARAMETER` itself, but the parameter whose name is stored as the value
of `PARAMETER`. If the parameter `PARAMETER` has the value \"`TEMP`\",
of `PARAMETER`. If the parameter `PARAMETER` has the value "`TEMP`",
then `${!PARAMETER}` will expand to the value of the parameter named
`TEMP`:
@ -193,7 +193,7 @@ of an array, the length of a string, or number of elements in an array
indirectly (see [syntax/arrays#indirection](../syntax/arrays.md#indirection)
for workarounds). Additionally, the `!`-prefixed parameter expansion
conflicts with ksh-like shells which have the more powerful
\"name-reference\" form of indirection, where the exact same syntax is
"name-reference" form of indirection, where the exact same syntax is
used to expand to the name of the variable being referenced.
Indirect references to [array names](../syntax/arrays.md) are also possible
@ -235,13 +235,13 @@ of words in the variable while `~~` reverses case for all. Thanks to
</wrap>
[**Example: Rename all `*.txt` filenames to lowercase**]{.underline}
<u>**Example: Rename all `*.txt` filenames to lowercase**</u>
for file in *.txt; do
mv "$file" "${file,,}"
done
[**Note:**]{.underline} Case modification is a handy feature you can
<u>**Note:**</u> Case modification is a handy feature you can
apply to a name or a title. Or is it? Case modification was an important
aspect of the Bash 4 release. Bash version 4, RC1 would perform word
splitting, and then case modification, resulting in title case (where
@ -271,9 +271,6 @@ Assume: `array=(This is some Text)`
- `echo "${array[@]^^}"`
- => `THIS IS SOME TEXT`
```{=html}
<!-- -->
```
* ''echo "${array[2]^^}"''
* => ''SOME''
@ -288,7 +285,7 @@ string `PREFIX`. The elements of the list are separated by the first
character in the `IFS`-variable (<space> by default).
This will show all defined variable names (not values!) beginning with
\"BASH\":
"BASH":
$ echo ${!BASH*}
BASH BASH_ARGC BASH_ARGV BASH_COMMAND BASH_LINENO BASH_SOURCE BASH_SUBSHELL BASH_VERSINFO BASH_VERSION
@ -319,9 +316,9 @@ Example string (*just a quote from a big man*):
`${PARAMETER#PATTERN}` and `${PARAMETER##PATTERN}`
This form is to remove the described [pattern](../syntax/pattern.md) trying
to **match it from the beginning of the string**. The operator \"`#`\"
to **match it from the beginning of the string**. The operator "`#`"
will try to remove the shortest text matching the pattern, while
\"`##`\" tries to do it with the longest text matching. Look at the
"`##`" tries to do it with the longest text matching. Look at the
following examples to get the idea (matched text ~~marked striked~~,
remember it will be removed!):
@ -347,7 +344,7 @@ from the end.
### Common use
[**How the heck does that help to make my life easier?**]{.underline}
<u>**How the heck does that help to make my life easier?**</u>
Well, maybe the most common use for it is to **extract parts of a
filename**. Just look at the following list with examples:
@ -410,7 +407,7 @@ The first one (*one slash*) is to only substitute **the first
occurrence** of the given pattern, the second one (*two slashes*) is to
substitute **all occurrences** of the pattern.
First, let's try to say \"happy\" instead of \"conservative\" in our
First, let's try to say "happy" instead of "conservative" in our
example string:
${MYSTRING//conservative/happy}
@ -418,26 +415,26 @@ example string:
=>
`Be liberal in what you accept, and conservativehappy in what you send`
Since there is only one \"conservative\" in that example, it really
Since there is only one "conservative" in that example, it really
doesn't matter which of the two forms we use.
Let's play with the word \"in\", I don't know if it makes any sense,
but let's substitute it with \"by\".
Let's play with the word "in", I don't know if it makes any sense,
but let's substitute it with "by".
[**First form: Substitute first occurrence**]{.underline}
<u>**First form: Substitute first occurrence**</u>
${MYSTRING/in/by}
=> `Be liberal inby what you accept, and conservative in what you send`
[**Second form: Substitute all occurrences**]{.underline}
<u>**Second form: Substitute all occurrences**</u>
${MYSTRING//in/by}
=>
`Be liberal inby what you accept, and conservative inby what you send`
[**Anchoring**]{.underline} Additionally you can \"anchor\" an
<u>**Anchoring**</u> Additionally you can "anchor" an
expression: A `#` (hashmark) will indicate that your expression is
matched against the beginning portion of the string, a `%`
(percent-sign) will do it for the end portion.
@ -478,7 +475,7 @@ expanded. Again, a quote from a big man, to have a test text:
MYSTRING="Be liberal in what you accept, and conservative in what you send"
Using echo `${#MYSTRING}`\...
Using echo `${#MYSTRING}`...
=> `64`
@ -493,7 +490,7 @@ There's not much to say about it, mh?
For [arrays](../syntax/arrays.md), this expansion type has two meanings:
- For **individual** elements, it reports the string length of the
element (as for every \"normal\" parameter)
element (as for every "normal" parameter)
- For the **mass subscripts** `@` and `*` it reports the number of set
elements in the array
@ -502,11 +499,11 @@ Example:
Assume: `array=(This is a text)`
- `echo ${#array[1]}`
- => 2 (the word \"is\" has a length of 2)
- => 2 (the word "is" has a length of 2)
- `echo ${#array[@]}`
- => 4 (the array contains 4 elements)
[**Attention:**]{.underline} The number of used elements does not need
<u>**Attention:**</u> The number of used elements does not need
to conform to the highest index. Sparse arrays are possible in Bash,
that means you can have 4 elements, but with indexes 1, 7, 20, 31. **You
can't loop through such an array with a counter loop based on the
@ -593,7 +590,7 @@ Example:
Assume: `array=(This is a text)`
- `echo ${array[0]:2:2}`
- => `is` (the \"is\" in \"This\", array element 0)
- => `is` (the "is" in "This", array element 0)
- `echo ${array[@]:1:2}`
- => `is a` (from element 1 inclusive, 2 elements are expanded,
i.e. element 1 and 2)
@ -621,7 +618,7 @@ useful, you need to put that parameter syntax in.
read -p "Enter your gender (just press ENTER to not tell us): " GENDER
echo "Your gender is ${GENDER:-a secret}."
It will print \"Your gender is a secret.\" when you don't enter the
It will print "Your gender is a secret." when you don't enter the
gender. Note that the default value is **used on expansion time**, it is
**not assigned to the parameter**.
@ -712,7 +709,7 @@ Let's change our code example from above:
### Assign a default value: Arrays
For [arrays](../syntax/arrays.md) this expansion type is limited. For an
individual index, it behaves like for a \"normal\" parameter, the
individual index, it behaves like for a "normal" parameter, the
default value is assigned to this one element. The mass-expansion
subscripts `@` and `*` **can not be used here** because it's not
possible to assign to them!
@ -732,7 +729,7 @@ you can specify**:
The above code will simply add a warning if `JAVAPATH` is set (because
it could influence the startup behaviour of that imaginary application).
Some more unrealistic example\... Ask for some flags (for whatever
Some more unrealistic example... Ask for some flags (for whatever
reason), and then, if they were set, print a warning and also print the
flags:
@ -761,7 +758,7 @@ if variables you need (and that can be empty) are undefined:
### Use an alternate value: Arrays
Similar to the cases for [arrays](../syntax/arrays.md) to expand to a default
value, this expansion behaves like for a \"normal\" parameter when using
value, this expansion behaves like for a "normal" parameter when using
individual array elements by index, but reacts differently when using
the mass-expansion subscripts `@` and `*`:
@ -830,9 +827,6 @@ Removing the first 6 characters from a text string:
<a b cfoo> <a b cfoo> <a> <b> <cfoo>
`
```{=html}
<!-- -->
```
- Almost all shells disagree about the treatment of an unquoted `$@`,
`${arr[@]}`, `$*`, and `${arr[*]}` when
[IFS](http://mywiki.wooledge.org/IFS) is set to null. POSIX is
@ -877,9 +871,6 @@ Removing the first 6 characters from a text string:
pathname expansion and word-splitting to the results, except for
zsh, which doesn't do pathname expansion in its default mode.
```{=html}
<!-- -->
```
- Additionally, shells disagree about various wordsplitting behaviors,
the behavior of inserting delimiter characters from IFS in `$*`, and
the way adjacent arguments are concatenated, when IFS is modified in
@ -906,35 +897,23 @@ Removing the first 6 characters from a text string:
possible side-effect that can affect expansion halfway through
expansion that way.
```{=html}
<!-- -->
```
- As previously mentioned, the Bash form of indirection by prefixing a
parameter expansion with a `!` conflicts with the same syntax used
by mksh, zsh, and ksh93 for a different purpose. Bash will
\"slightly\" modify this expansion in the next version with the
"slightly" modify this expansion in the next version with the
addition of namerefs.
```{=html}
<!-- -->
```
- Bash (and most other shells) don't allow .'s in identifiers. In
ksh93, dots in variable names are used to reference methods (i.e.
\"Discipline Functions\"), attributes, special shell variables, and
to define the \"real value\" of an instance of a class.
"Discipline Functions"), attributes, special shell variables, and
to define the "real value" of an instance of a class.
```{=html}
<!-- -->
```
- In ksh93, the `_` parameter has even more uses. It is used in the
same way as `self` in some object-oriented languages; as a
placeholder for some data local to a class; and also as the
mechanism for class inheritance. In most other contexts, `_` is
compatible with Bash.
```{=html}
<!-- -->
```
- Bash only evaluates the subscripts of the slice expansion
(`${x:y:z}`) if the parameter is set (for both nested expansions and
arithmetic). For ranges, Bash evaluates as little as possible, i.e.,
@ -954,13 +933,10 @@ Removing the first 6 characters from a text string:
### Quote Nesting
- In most shells, when dealing with an \"alternate\" parameter
- In most shells, when dealing with an "alternate" parameter
expansion that expands to multiple words, and nesting such
expansions, not all combinations of nested quoting are possible.
```{=html}
<!-- -->
```
# Bash
$ typeset -a a=(meh bleh blerg) b
$ IFS=e
@ -1007,7 +983,7 @@ Consider the following (only slightly far-fetched) code:
"${someCmd[@]-"$someOtherCmd" arg2 "${otherArgs[@]}"}" arg5
This final line is perhaps not the most obvious, but I\'ve run into
This final line is perhaps not the most obvious, but I've run into
cases were this type of logic can be desirable and realistic. We can
deduce what was intended:

View File

@ -27,7 +27,7 @@ All three forms have the very same purpose: **They give you general
control over parsing, expansion and expansion results.**
Besides these basic variants, there are some special quoting methods
(like interpreting ANSI-C escapes in a string) you\'ll meet below.
(like interpreting ANSI-C escapes in a string) you'll meet below.
:!: **ATTENTION** :!: The quote characters (`"`, double quote and `'`,
single quote) are a syntax element that influence parsing. It is not
@ -77,7 +77,7 @@ beautify your code:
}
The backslash can be used to mask every character that has a special
meaning to bash. [Exception:]{.underline} Inside a single-quoted string
meaning to bash. <u>Exception:</u> Inside a single-quoted string
(see below).
## Weak quoting
@ -105,7 +105,7 @@ unless you have a file named `*`, spit out an error.
Will work as expected. `$PATH` is expanded, because it's double (weak)
quoted.
If a backslash in double quotes (\"weak quoting\") occurs, there are 2
If a backslash in double quotes ("weak quoting") occurs, there are 2
ways to deal with it
- if the baskslash is followed by a character that would have a
@ -131,7 +131,7 @@ it's surrounded by strong quotes.
In practise that means, to produce a text like `Here's my test...` as a
single-quoted string, you have to leave and re-enter the single quoting
to get the character \"`'`\" as literal text:
to get the character "`'`" as literal text:
# WRONG
echo 'Here's my test...'
@ -151,25 +151,25 @@ C-like escape sequences. The Syntax is:
where the following escape sequences are decoded in `string`:
Code Meaning
-------------- -------------------------------------------------------------------------------------------------------------------------------------
`\"` double-quote
`\'` single-quote
`\\` backslash
`\a` terminal alert character (bell)
`\b` backspace
`\e` escape (ASCII 033)
`\E` escape (ASCII 033) **\\E is non-standard**
`\f` form feed
`\n` newline
`\r` carriage return
`\t` horizontal tab
`\v` vertical tab
`\cx` a control-x character, for example, `$'\cZ'` to print the control sequence composed of Ctrl-Z (`^Z`)
`\uXXXX` Interprets `XXXX` as a hexadecimal number and prints the corresponding character from the character set (4 digits) (Bash 4.2-alpha)
`\UXXXXXXXX` Interprets `XXXX` as a hexadecimal number and prints the corresponding character from the character set (8 digits) (Bash 4.2-alpha)
`\nnn` the eight-bit character whose value is the octal value nnn (one to three digits)
`\xHH` the eight-bit character whose value is the hexadecimal value HH (one or two hex digits)
|Code|Meaning|
|----|-------|
|`\"`|double-quote|
|`\'`|single-quote|
|`\\`|backslash|
|`\a`|terminal alert character (bell)|
|`\b`|backspace|
|`\e`|escape (ASCII 033)|
|`\E`|escape (ASCII 033) **\E is non-standard**|
|`\f`|form feed|
|`\n`|newline|
|`\r`|carriage return|
|`\t`|horizontal tab|
|`\v`|vertical tab|
|`\cx`|a control-x character, for example, `$'\cZ'` to print the control sequence composed of Ctrl-Z (`^Z`)|
|`\uXXXX`|Interprets `XXXX` as a hexadecimal number and prints the corresponding character from the character set (4 digits) (Bash 4.2-alpha)|
|`\UXXXXXXXX`|Interprets `XXXX` as a hexadecimal number and prints the corresponding character from the character set (8 digits) (Bash 4.2-alpha)|
|`\nnn`|the eight-bit character whose value is the octal value nnn (one to three digits)|
|`\xHH`|the eight-bit character whose value is the hexadecimal value HH (one or two hex digits)|
This is especially useful when you want to pass special characters as
arguments to some programs, like passing a newline to sed.
@ -181,8 +181,8 @@ The `$'...'` syntax comes from ksh93, but is portable to most modern
shells including pdksh. A
[specification](http://austingroupbugs.net/view.php?id=249#c590) for it
was accepted for SUS issue 7. There are still some stragglers, such as
most ash variants including dash, (except busybox built with \"bash
compatibility\" features).
most ash variants including dash, (except busybox built with "bash
compatibility" features).
## I18N/L10N
@ -197,7 +197,7 @@ quoted string.
If the string was replaced (translated), the result is double quoted.
In case you\'re a C programmer: The purpose of `$"..."` is the same as
In case you're a C programmer: The purpose of `$"..."` is the same as
for `gettext()` or `_()`.
For useful examples to localize your scripts, please see [Appendix I of
@ -216,7 +216,7 @@ iterate through. The list can also be in a variable:
mylist="DOG CAT BIRD HORSE"
**[WRONG]{.underline}** way to iterate through this list:
**<u>WRONG</u>** way to iterate through this list:
for animal in "$mylist"; do
echo $animal
@ -226,7 +226,7 @@ Why? Due to the double-quotes, technically, the expansion of `$mylist`
is seen as **one word**. The for loop iterates exactly one time, with
`animal` set to the whole list.
**[RIGHT]{.underline}** way to iterate through this list:
**<u>RIGHT</u>** way to iterate through this list:
for animal in $mylist; do
echo $animal
@ -251,7 +251,7 @@ test string with spaces:
mystring="my string"
And now check that string against the word \"testword\":
And now check that string against the word "testword":
[ $mystring = testword ] # WRONG!
@ -272,20 +272,16 @@ So what you really want to do is:
Now the command has three parameters, which makes sense for a binary
(two argument) operator.
**[Hint:]{.underline}** Inside the [conditional
**<u>Hint:</u>** Inside the [conditional
expression](../syntax/ccmd/conditional_expression.md) (`[[ ]]`) Bash doesn't
perform word splitting, and thus you don't need to quote your variable
references - they are always seen as \"one word\".
references - they are always seen as "one word".
## See also
- Internal: [Some words about words\...](../syntax/words.md)
- Internal: [Some words about words...](../syntax/words.md)
- Internal: [Word splitting](../syntax/expansion/wordsplit.md)
- Internal: [Introduction to expansions and
substitutions](../syntax/expansion/intro.md)
```{=html}
<!-- -->
```
- External: [Grymore:
Shellquoting](http://www.grymoire.com/Unix/Quote.html)

View File

@ -1,6 +1,8 @@
# Redirection
<wrap left todo>Fix me: To be continued</wrap>\
!!! warning "FIXME"
To be continued
Redirection makes it possible to control where the output of a command
goes to, and where the input of a command comes from. It's a mighty
tool that, together with pipelines, makes the shell powerful. The
@ -10,15 +12,18 @@ be executed](../syntax/grammar/parser_exec.md).
Under normal circumstances, there are 3 files open, accessible by the
file descriptors 0, 1 and 2, all connected to your terminal:
Name FD Description
---------- ---- --------------------------------------------------------
`stdin` 0 standard input stream (e.g. keyboard)
`stdout` 1 standard output stream (e.g. monitor)
`stderr` 2 standard error output stream (usually also on monitor)
|Name|FD|Description|
|----|--|-----------|
|`stdin`|0|standard input stream (e.g. keyboard)|
|`stdout`|1|standard output stream (e.g. monitor)|
|`stderr`|2|standard error output stream (usually also on monitor)|
<wrap center info>The terms \"monitor\" and \"keyboard\" refer to the
same device, the **terminal** here. Check your preferred UNIX(r)-FAQ for
details, I\'m too lazy to explain what a terminal is ;-) </wrap>
!!! info "INFO"
The terms "monitor" and "keyboard" refer to the
same device, the **terminal** here. Check your preferred UNIX(r)-FAQ for
details, I'm too lazy to explain what a terminal is ;-)
Both, `stdout` and `stderr` are output file descriptors. Their
difference is the **convention** that a program outputs payload on
@ -33,7 +38,7 @@ this descriptor, you just use the number:
cat some_file.txt 2>/dev/null
Whenever you **reference** a descriptor, to point to its current target
file, then you use a \"`&`\" followed by a the descriptor number:
file, then you use a "`&`" followed by a the descriptor number:
# this executes the echo-command and redirects its normal output (stdout) to the standard error target
echo "There was an error" 1>&2
@ -45,26 +50,27 @@ these examples are equivalent:
cat >new.txt foo.txt bar.txt
>new.txt cat foo.txt bar.txt
<wrap center important>Every redirection operator takes one or two
words as operands. If you have to use operands (e.g. filenames to
redirect to) that contain spaces you **must** quote them!</wrap>
!!! info "important"
Every redirection operator takes one or two
words as operands. If you have to use operands (e.g. filenames to
redirect to) that contain spaces you **must** quote them!
## Valid redirection targets and sources
This syntax is recognized whenever a `TARGET` or a `SOURCE`
specification (like below in the details descriptions) is used.
Syntax Description
---------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------
`FILENAME` references a normal, ordinary filename from the filesystem (which can of course be a FIFO, too. Simply everything you can reference in the filesystem)
`&N` references the current target/source of the filedescriptor `N` (\"duplicates\" the filedescriptor)
`&-` closes the redirected filedescriptor, useful instead of `> /dev/null` constructs (`> &-`)
`/dev/fd/N` duplicates the filedescriptor `N`, if `N` is a valid integer
`/dev/stdin` duplicates filedescriptor 0 (`stdin`)
`/dev/stdout` duplicates filedescriptor 1 (`stdout`)
`/dev/stderr` duplicates filedescriptor 2 (`stderr`)
`/dev/tcp/HOST/PORT` assuming `HOST` is a valid hostname or IP address, and `PORT` is a valid port number or service name: redirect from/to the corresponding TCP socket
`/dev/udp/HOST/PORT` assuming `HOST` is a valid hostname or IP address, and `PORT` is a valid port number or service name: redirect from/to the corresponding UDP socket
|Syntax|Description|
|------|-----------|
|`FILENAME`|references a normal, ordinary filename from the filesystem (which can of course be a FIFO, too. Simply everything you can reference in the filesystem)|
|`&N`|references the current target/source of the filedescriptor `N` ("duplicates" the filedescriptor)|
|`&-`|closes the redirected filedescriptor, useful instead of `> /dev/null` constructs (`> &-`)|
|`/dev/fd/N`|duplicates the filedescriptor `N`, if `N` is a valid integer|
|`/dev/stdin`|duplicates filedescriptor 0 (`stdin`)|
|`/dev/stdout`|duplicates filedescriptor 1 (`stdout`)|
|`/dev/stderr`|duplicates filedescriptor 2 (`stderr`)|
|`/dev/tcp/HOST/PORT`|assuming `HOST` is a valid hostname or IP address, and `PORT` is a valid port number or service name: redirect from/to the corresponding TCP socket|
|`/dev/udp/HOST/PORT`|assuming `HOST` is a valid hostname or IP address, and `PORT` is a valid port number or service name: redirect from/to the corresponding UDP socket|
If a target/source specification fails to open, the whole redirection
operation fails. Avoid referencing file descriptors above 9, since you
@ -106,9 +112,10 @@ specified target. It's **equivalent** to
Since Bash4, there's `&>>TARGET`, which is equivalent to
`>> TARGET 2>&1`.
<wrap center important>This syntax is deprecated and should not be
used. See the page about [obsolete and deprecated
syntax](../scripting/obsolete.md).</wrap>
!!! info "important"
This syntax is deprecated and should not be
used. See the page about [obsolete and deprecated
syntax](../scripting/obsolete.md).
## Appending redirected output and error output
@ -145,7 +152,7 @@ omitted, filedescriptor 0 (`stdin`) is assumed.
TAG
A here-document is an input redirection using source data specified
directly at the command line (or in the script), no \"external\" source.
directly at the command line (or in the script), no "external" source.
The redirection-operator `<<` is used together with a tag `TAG` that's
used to mark the end of input later:
@ -178,11 +185,12 @@ here-documents.
The tag you use **must** be the only word in the line, to be recognized
as end-of-here-document marker.
<wrap center info>It seems that here-documents (tested on versions
`1.14.7`, `2.05b` and `3.1.17`) are correctly terminated when there is
an EOF before the end-of-here-document tag. The reason is unknown, but
it seems to be done on purpose. Bash 4 introduced a warning message when
end-of-file is seen before the tag is reached.</wrap>
!!! info "info"
It seems that here-documents (tested on versions
`1.14.7`, `2.05b` and `3.1.17`) are correctly terminated when there is
an EOF before the end-of-here-document tag. The reason is unknown, but
it seems to be done on purpose. Bash 4 introduced a warning message when
end-of-file is seen before the tag is reached.
## Here strings
@ -201,7 +209,7 @@ The here-string will append a newline (`\n`) to the data.
## Multiple redirections
More redirection operations can occur in a line of course. The order is
**important**! They\'re evaluated from **left to right**. If you want to
**important**! They're evaluated from **left to right**. If you want to
redirect both, `stderr` and `stdout` to the same file (like `/dev/null`,
to hide it), this is **the wrong way**:
@ -216,12 +224,12 @@ Why? Relatively easy:
- initially, `stdout` points to your terminal (you read it)
- same applies to `stderr`, it's connected to your terminal
- `2>&1` redirects `stderr` away from the terminal to the target for
`stdout`: **the terminal** (again\...)
`stdout`: **the terminal** (again...)
- `1>/dev/null` redirects `stdout` away from your terminal to the file
`/dev/null`
What remains? `stdout` goes to `/dev/null`, `stderr` still (or better:
\"again\") goes to the terminal. You have to swap the order to make it
"again") goes to the terminal. You have to swap the order to make it
do what you want:
``` bash

File diff suppressed because it is too large Load Diff

View File

@ -10,12 +10,13 @@ tags:
- recognition
---
# Words\...
# Words...
FIXME This article needs a review, it covers two topics (command line
splitting and word splitting) and mixes both a bit too much. But in
general, it's still usable to help understand this behaviour, it's
\"wrong but not wrong\".
!!! warning "FIXME"
This article needs a review, it covers two topics (command line
splitting and word splitting) and mixes both a bit too much. But in
general, it's still usable to help understand this behaviour, it's
"wrong but not wrong".
One fundamental principle of Bash is to recognize words entered at the
command prompt, or under other circumstances like variable-expansion.
@ -32,7 +33,7 @@ by a space. When you enter an echo command at the Bash prompt, Bash will
look for those special characters, and use them to separate the
parameters.
You don't know what I\'m talking about? I\'m talking about this:
You don't know what I'm talking about? I'm talking about this:
$ echo Hello little world
Hello little world
@ -48,9 +49,9 @@ blank characters is treated as a single blank.** Here's an example:
Bash splits the command line at the blanks into words, then it calls
echo with **each word as an argument**. In this example, echo is called
with three arguments: \"`Hello`\", \"`little`\" and \"`world`\"!
with three arguments: "`Hello`", "`little`" and "`world`"!
[Does that mean we can't echo more than one Space?]{.underline} Of
<u>Does that mean we can't echo more than one Space?</u> Of
course not! Bash treats blanks as special characters, but there are two
ways to tell Bash not to treat them special: **Escaping** and
**quoting**.
@ -63,9 +64,9 @@ Escaping is done by preceeding the character with a backslash:
Hello little world
None of the escaped spaces will be used to perform word splitting. Thus,
echo is called with one argument: \"`Hello little world`\".
echo is called with one argument: "`Hello little world`".
Bash has a mechanism to \"escape\" an entire string: **Quoting**. In the
Bash has a mechanism to "escape" an entire string: **Quoting**. In the
context of command-splitting, which this section is about, it doesn't
matter which kind of quoting you use: weak quoting or strong quoting,
both cause Bash to not treat spaces as special characters:
@ -76,7 +77,7 @@ both cause Bash to not treat spaces as special characters:
$ echo 'Hello little world'
Hello little world
[What is it all about now?]{.underline} Well, for example imagine a
<u>What is it all about now?</u> Well, for example imagine a
program that expects a filename as an argument, like cat. Filenames can
have spaces in them:
@ -141,41 +142,37 @@ and the first review is:
echo The file is named $MYFILE
The parser will scan for blanks and mark the relevant words (\"splitting
the command line\"):
The parser will scan for blanks and mark the relevant words ("splitting
the command line"):
Initial command line splitting:
--------------------------------- -------- -------- -------- --------- -----------
Word 1 Word 2 Word 3 Word 4 Word 5 Word 6
`echo` `The` `file` `is` `named` `$MYFILE`
| Initial command line splitting: | | | | | |
|---------------------------------|--------|--------|--------|---------|-----------|
| Word 1 | Word 2 | Word 3 | Word 4 | Word 5 | Word 6 |
| `echo` | `The` | `file` | `is` | `named` | `$MYFILE` |
A [parameter/variable expansion](../syntax/pe.md) is part of that command
line, Bash will perform the substitution, and the [word
splitting](../syntax/expansion/wordsplit.md) on the results:
Word splitting after substitution:
------------------------------------ -------- -------- -------- --------- -------- ------------
Word 1 Word 2 Word 3 Word 4 Word 5 Word 6 Word 7
`echo` `The` `file` `is` `named` `THE` `FILE.TXT`
| Word splitting after substitution: | | | | | | |
|------------------------------------|--------|--------|--------|---------|--------|------------|
| Word 1 | Word 2 | Word 3 | Word 4 | Word 5 | Word 6 | Word 7 |
| `echo` | `The` | `file` | `is` | `named` | `THE` | `FILE.TXT` |
Now let's imagine we quoted `$MYFILE`, the command line now looks like:
echo The file is named "$MYFILE"
Word splitting after substitution (quoted!):
---------------------------------------------- -------- -------- -------- --------- ----------------
Word 1 Word 2 Word 3 Word 4 Word 5 Word 6
`echo` `The` `file` `is` `named` `THE FILE.TXT`
| Word splitting after substitution (quoted!): | | | | | |
|----------------------------------------------|--------|--------|--------|---------|----------------|
| Word 1 | Word 2 | Word 3 | Word 4 | Word 5 | Word 6 |
| `echo` | `The` | `file` | `is` | `named` | `THE FILE.TXT` |
***Bold Text*72i love this world**===== See also =====
# See also
- Internal: [Quoting and character escaping](../syntax/quoting.md)
- Internal: [Word splitting](../syntax/expansion/wordsplit.md)
- Internal: [Introduction to expansions and
substitutions](../syntax/expansion/intro.md)
```{=html}
<!-- -->
```
- External: [Grymore:
Shellquoting](http://www.grymoire.com/Unix/Quote.html)