mirror of
https://github.com/flokoe/bash-hackers-wiki.git
synced 2024-11-25 07:43:42 +01:00
Updated table formatting, call-outs, html comments, improper escapes.
This commit is contained in:
parent
de70cb886e
commit
cd90135cce
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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]: ...
|
||||
|
@ -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
|
||||
|
@ -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<n>" 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.
|
||||
|
@ -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!
|
||||
|
||||
!!! 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](../../printf?&.md#using_printf_inside_of_awk). </div>
|
||||
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,14 +53,15 @@ 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
|
||||
!!! 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.
|
||||
|
||||
@ -65,12 +69,12 @@ this opens up the possibility of an easy code injection vulnerability.
|
||||
hi
|
||||
declare -a x='([0]="hi")'
|
||||
|
||||
\...where the echo can of course be replaced with any arbitrary command.
|
||||
...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>
|
||||
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,7 +101,8 @@ 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
|
||||
!!! 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
|
||||
@ -105,7 +110,6 @@ octal number (`00` to `07`!):
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
### 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,17 +410,12 @@ 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
|
||||
@ -444,6 +435,7 @@ fmt++;
|
||||
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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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,15 +49,17 @@ 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!
|
||||
|
||||
```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
|
||||
@ -94,7 +96,9 @@ FIXME Add more examples!
|
||||
fi
|
||||
find "$@"
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# Using collapsing functions to turn debug messages on/off
|
||||
|
||||
@ -104,3 +108,4 @@ FIXME Add more examples!
|
||||
# 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
|
||||
```
|
||||
|
@ -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
|
||||
|
@ -13,7 +13,7 @@ $ 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:
|
||||
|
||||
@ -30,7 +30,7 @@ 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
|
||||
@ -62,7 +62,7 @@ $ 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)
|
||||
@ -83,7 +83,7 @@ $ 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.)
|
||||
@ -107,7 +107,7 @@ 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
|
||||
|
@ -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),
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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> 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< 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
|
||||
!!! 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.</note>
|
||||
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,36 +633,20 @@ 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
|
||||
|
||||
@ -681,6 +660,7 @@ recommendations:
|
||||
# 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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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).
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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|
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
!!! 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! </note>
|
||||
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/>
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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 ;-)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 => 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 <condition> ? <result-if-true> : <result-if-false>|
|
||||
|`<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 -> 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,8 +292,9 @@ 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."
|
||||
|
||||
For example,
|
||||
|
||||
This non-equivalence of code behavior deserves some attention. Consider
|
||||
what happens if v happens to be zero in the expression below:
|
||||
@ -315,7 +306,7 @@ echo $?
|
||||
|
||||
1
|
||||
|
||||
(\"FAILURE\")
|
||||
("FAILURE")
|
||||
|
||||
``` bash
|
||||
v=$((v + 0))
|
||||
@ -324,7 +315,7 @@ echo $?
|
||||
|
||||
0
|
||||
|
||||
(\"SUCCESS\")
|
||||
("SUCCESS")
|
||||
|
||||
The return code behavior is not equivalent to the arithmetic behavior,
|
||||
as has been noted.
|
||||
@ -339,10 +330,10 @@ echo $?
|
||||
|
||||
0
|
||||
|
||||
(\"SUCCESS\")
|
||||
("SUCCESS")
|
||||
|
||||
This change in code behavior was discovered once the script was run
|
||||
under set -e. </WRAP>
|
||||
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)
|
||||
|
@ -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
|
||||
!!! 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. </note>
|
||||
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,42 +151,30 @@ 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
|
||||
!!! 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.
|
||||
@ -205,7 +194,7 @@ To avoid this, **always quote** the array name and index:
|
||||
unset -v 'x[1]'
|
||||
|
||||
This applies generally to all commands which take variable names as
|
||||
arguments. Single quotes preferred. </note>
|
||||
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
|
||||
!!! 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.
|
||||
</note>
|
||||
|
||||
### 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>
|
||||
|
@ -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
|
||||
!!! 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). </wrap>
|
||||
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
|
||||
|
@ -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
|
||||
@ -177,7 +174,7 @@ value (8 bits).
|
||||
|
||||
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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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 '<' and '>' (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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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,14 +208,14 @@ 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
|
||||
|
||||
!!! 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
|
||||
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.
|
||||
|
||||
@ -237,14 +228,13 @@ any number of arguments.
|
||||
|
||||
printf 'eval printf "$arg"%s' "$(braceify 1000000)"
|
||||
|
||||
\"Braceify\" generates the expansion code itself. In this example we
|
||||
"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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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\'
|
||||
|
@ -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
|
||||
|
@ -42,7 +42,8 @@ from a file).
|
||||
|
||||
### Scope
|
||||
|
||||
<note important> Note: According to multiple comments and sources, the
|
||||
!!! 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
|
||||
@ -51,12 +52,12 @@ function scope. See
|
||||
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>
|
||||
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:
|
||||
!!! 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?* </WRAP>
|
||||
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
|
||||
|
@ -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
|
||||
!!! 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=:~
|
||||
|
||||
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
|
||||
|
@ -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>
|
||||
- <space>
|
||||
- <tab>
|
||||
- <newline>
|
||||
|
||||
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
|
||||
>>nothing<<) 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.
|
||||
|
||||
|
@ -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>
|
||||
|
||||
</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
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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`
|
||||
- => `Hello world`
|
||||
- => `hello world`
|
||||
- Pattern `Hello*` matches (for example)
|
||||
- => `Hello world`
|
||||
- => `Helloworld`
|
||||
- => `HelloWoRlD`
|
||||
- => `Hello`
|
||||
- => `Hello world`
|
||||
- => `Helloworld`
|
||||
- => `HelloWoRlD`
|
||||
- => `Hello`
|
||||
- Pattern `Hello world[[:punct:]]` matches (for example)
|
||||
- => `Hello world!`
|
||||
- => `Hello world.`
|
||||
- => `Hello world+`
|
||||
- => `Hello world?`
|
||||
- => `Hello world!`
|
||||
- => `Hello world.`
|
||||
- => `Hello world+`
|
||||
- => `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!`
|
||||
- => `\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
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
||||
!!! 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 ;-) </wrap>
|
||||
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
|
||||
!!! 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!</wrap>
|
||||
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
|
||||
!!! info "important"
|
||||
This syntax is deprecated and should not be
|
||||
used. See the page about [obsolete and deprecated
|
||||
syntax](../scripting/obsolete.md).</wrap>
|
||||
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
|
||||
!!! 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.</wrap>
|
||||
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
@ -10,12 +10,13 @@ tags:
|
||||
- recognition
|
||||
---
|
||||
|
||||
# Words\...
|
||||
# Words...
|
||||
|
||||
FIXME This article needs a review, it covers two topics (command line
|
||||
!!! 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\".
|
||||
"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)
|
||||
|
Loading…
Reference in New Issue
Block a user