mirror of
https://github.com/flokoe/bash-hackers-wiki.git
synced 2024-11-01 14:53:06 +01:00
Merge pull request #19 from sahal/formatting/fixes
Updated table formatting, call-outs, html comments, improper escapes.
This commit is contained in:
commit
681cee9723
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
The `caller` builtin command is used to print execution frames of
|
The `caller` builtin command is used to print execution frames of
|
||||||
subroutine calls. Without giving a framenumber, the topmost execution
|
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.
|
filename.
|
||||||
|
|
||||||
When an execution frame number is given (0 - topmost), the linenumber,
|
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
|
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
|
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
|
frame (0). The topmost frame is the "caller of the die function", in
|
||||||
this case function \"f1\".
|
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.
|
purposes.
|
||||||
|
|
||||||
The code is made very simple, just to show the basic 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
|
[Bashdb](http://bashdb.sourceforge.net/) can assist in using some of
|
||||||
Bash's more advanced debug features.
|
Bash's more advanced debug features.
|
||||||
- The Bash manpage and help text specifies that the argument to
|
- 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
|
actually allowed, with no special interpretation of an
|
||||||
\"expression\" as far as we can tell.
|
"expression" as far as we can tell.
|
||||||
|
|
||||||
## Portability considerations
|
## Portability considerations
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ Below, `[-+]X` indicates an attribute, use `-X` to set the attribute,
|
|||||||
|
|
||||||
`[-+]A` make NAMEs associative arrays
|
`[-+]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)
|
`-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)
|
`-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)
|
`[-+]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.\
|
`[-+]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.\
|
''`${!NAME}`'' reveals the reference variable name, VALUE.
|
||||||
Use `unset -n NAME` to unset the variable. (`unset -v NAME` unsets the VALUE variable.)\
|
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.
|
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
|
`-p` display the attributes and value of each NAME
|
||||||
|
|
||||||
`[-+]r` make NAMEs readonly (removing with `+r` is valid syntax, but not possible)
|
`[-+]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)
|
`[-+]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 assignment to a readonly variable
|
||||||
!= 0 removing the readonly-attribute from 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 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`
|
!= 0 attemt to display a non-existent function with `-f`
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
Unix shells offer very few datatypes. Bash and some other shells extend
|
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
|
attributes specified by POSIX are `export` and `readonly`, which are set
|
||||||
by their own dedicated builtins. Datatypes in bash have a few other
|
by their own dedicated builtins. Datatypes in bash have a few other
|
||||||
interesting capabilities such as the ability to modify data on
|
interesting capabilities such as the ability to modify data on
|
||||||
@ -92,7 +92,7 @@ assignment.
|
|||||||
|
|
||||||
### Display defined functions
|
### 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
|
$ declare -f
|
||||||
foo ()
|
foo ()
|
||||||
@ -104,7 +104,7 @@ assignment.
|
|||||||
echo "Hello World!"
|
echo "Hello World!"
|
||||||
}
|
}
|
||||||
|
|
||||||
\...or just a specific defined function.
|
...or just a specific defined function.
|
||||||
|
|
||||||
$ declare -f foo
|
$ declare -f foo
|
||||||
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
|
considers `typeset` a special builtin, while Bash does not - even in
|
||||||
POSIX mode. If you use `typeset`, you should attempt to only use it
|
POSIX mode. If you use `typeset`, you should attempt to only use it
|
||||||
in portable ways.
|
in portable ways.
|
||||||
- **todo** nameref portability\...
|
- **todo** nameref portability...
|
||||||
|
|
||||||
## See also
|
## See also
|
||||||
|
|
||||||
|
@ -56,17 +56,14 @@ if given.
|
|||||||
case `-n` is always treated as a string, and backslash escapes are
|
case `-n` is always treated as a string, and backslash escapes are
|
||||||
interpreted by default. `dash` has the misfeature of following this
|
interpreted by default. `dash` has the misfeature of following this
|
||||||
and interpreting escapes by default, but includes a `-n` feature for
|
and interpreting escapes by default, but includes a `-n` feature for
|
||||||
suppressing newlines nevertheless.\
|
suppressing newlines nevertheless.
|
||||||
\
|
|
||||||
In practice, if you\'re able to assume a korn-like shell including
|
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
|
bash, mksh, or zsh, `echo` when used in simple cases is generally
|
||||||
reliable. For example, in the very common situation in which echo is
|
reliable. For example, in the very common situation in which echo is
|
||||||
supplied with a single argument and whose output is to have a
|
supplied with a single argument and whose output is to have a
|
||||||
newline appended, using `echo` is considered common practice.
|
newline appended, using `echo` is considered common practice.
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
- **Never use options to `echo`! *Ever*!** Any time you feel tempted
|
- **Never use options to `echo`! *Ever*!** Any time you feel tempted
|
||||||
to use `echo -e`, `-n`, or any other special feature of echo, **use
|
to use `echo -e`, `-n`, or any other special feature of echo, **use
|
||||||
[printf](../../commands/builtin/printf.md) instead!** If portability is a
|
[printf](../../commands/builtin/printf.md) instead!** If portability is a
|
||||||
@ -76,9 +73,6 @@ if given.
|
|||||||
\$\'\...\' \'\'if targeting only shells that support this special
|
\$\'\...\' \'\'if targeting only shells that support this special
|
||||||
quoting style.
|
quoting style.
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
- `ksh93` has a `print` command, which if coding specifically for
|
- `ksh93` has a `print` command, which if coding specifically for
|
||||||
`ksh93` should be preferred over `echo`.
|
`ksh93` should be preferred over `echo`.
|
||||||
[printf](../../commands/builtin/printf.md) still includes most of the
|
[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
|
### Using printf %q
|
||||||
|
|
||||||
The `printf %q` format string performs shell escaping on its arguments.
|
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.
|
through printf requiring another `eval` to peel off the escaping again.
|
||||||
|
|
||||||
while (( ++n <= 5 )) || ! evalBall="eval $evalBall"; do
|
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
|
`setopt POSIX_BUILTINS` -- looks like a regression). This works
|
||||||
correctly in Bash POSIX mode, Dash, and mksh.
|
correctly in Bash POSIX mode, Dash, and mksh.
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
- `eval` is another one of the few Bash builtins with keyword-like
|
- `eval` is another one of the few Bash builtins with keyword-like
|
||||||
conditional parsing of arguments that are in the form of compound
|
conditional parsing of arguments that are in the form of compound
|
||||||
assignments.
|
assignments.
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
$ ( eval a=( a b\\ c d ); printf '<%s> ' "${a[@]}"; echo ) # Only works in Bash.
|
$ ( eval a=( a b\\ c d ); printf '<%s> ' "${a[@]}"; echo ) # Only works in Bash.
|
||||||
<a> <b c> <d>
|
<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.
|
$ ( 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)
|
eval](http://mywiki.wooledge.org/BashFAQ/006#Assigning_indirect.2BAC8-reference_variables)
|
||||||
- [More indirection via
|
- [More indirection via
|
||||||
eval](http://fvue.nl/wiki/Bash:_Passing_variables_by_reference)
|
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.
|
`printf %q` work-alike for POSIX.
|
||||||
- [The \"magic alias\"
|
- [The "magic alias"
|
||||||
hack](http://www.chiark.greenend.org.uk/~sgtatham/aliases.html)
|
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
|
external `kill` command of the operating system to
|
||||||
|
|
||||||
- be able to use shell job specifications instead of Unix process IDs
|
- 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
|
limit is reached
|
||||||
|
|
||||||
### Options
|
### 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
|
right as an [arithmetic expression](../../syntax/arith_expr.md) and returns an
|
||||||
exit code according to the truth value of the rightmost expression.
|
exit code according to the truth value of the rightmost expression.
|
||||||
|
|
||||||
- 0 (TRUE) when `arg` evaluated to not 0 (arithmetic \"true\")
|
- 0 (TRUE) when `arg` evaluated to not 0 (arithmetic "true")
|
||||||
- 1 (FALSE) when `arg` evaluated to 0 (arithmetic \"false\")
|
- 1 (FALSE) when `arg` evaluated to 0 (arithmetic "false")
|
||||||
|
|
||||||
For this return code mapping, please see [this
|
For this return code mapping, please see [this
|
||||||
section](../../syntax/arith_expr.md#arithmetic_expressions_and_return_codes).
|
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
|
Unlike `((`, being a simple command `let` has its own environment. In
|
||||||
Bash, built-ins that can set variables process any arithmetic under
|
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.
|
the builtin unless the variable is also set or modified by the builtin.
|
||||||
This differs in other shells, such as ksh93, where environment
|
This differs in other shells, such as ksh93, where environment
|
||||||
assignments to regular builtins are always local even if the variable is
|
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.
|
choose `let` over `((` expecting it to work in more places.
|
||||||
- [expr(1)](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/expr.html#tag_20_42)
|
- [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 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
|
preferred. Both [arithmetic expansion](../../syntax/arith_expr.md)s and the
|
||||||
`[` test operator are specified by POSIX(r) and satisfy almost all
|
`[` test operator are specified by POSIX(r) and satisfy almost all
|
||||||
of expr's use-cases. Unlike `let`, `expr` cannot assign directly to
|
of expr's use-cases. Unlike `let`, `expr` cannot assign directly to
|
||||||
@ -108,4 +108,4 @@ needed.
|
|||||||
- Internal: [arithmetic evaluation compound
|
- Internal: [arithmetic evaluation compound
|
||||||
command](../../syntax/ccmd/arithmetic_eval.md)
|
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
|
have a builtin called `local`, but some such as `dash` and the
|
||||||
busybox shell do.
|
busybox shell do.
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
- The behavior of function scope is not defined by POSIX, however
|
- The behavior of function scope is not defined by POSIX, however
|
||||||
local variables are implemented widely by bourne-like shells, and
|
local variables are implemented widely by bourne-like shells, and
|
||||||
behavior differs substantially. Even the`dash` shell has local
|
behavior differs substantially. Even the`dash` shell has local
|
||||||
variables.
|
variables.
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
- In ksh93, using POSIX-style function definitions, `typeset` doesn't
|
- In ksh93, using POSIX-style function definitions, `typeset` doesn't
|
||||||
set `local` variables, but rather acts upon variables of the
|
set `local` variables, but rather acts upon variables of the
|
||||||
next-outermost scope (e.g. setting attributes). Using `typeset`
|
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
|
variables follow roughly
|
||||||
[lexical-scoping](http://community.schemewiki.org/?lexical-scope),
|
[lexical-scoping](http://community.schemewiki.org/?lexical-scope),
|
||||||
except that functions themselves don't have scope, just like Bash.
|
except that functions themselves don't have scope, just like Bash.
|
||||||
This means that even functions defined within a \"function's
|
This means that even functions defined within a "function's
|
||||||
scope\" don't have access to non-local variables except through
|
scope" don't have access to non-local variables except through
|
||||||
`namerefs`.
|
`namerefs`.
|
||||||
|
|
||||||
## See also
|
## 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
|
handling standard input (the other being `read`). `mapfile` reads lines
|
||||||
of standard input and assigns each to the elements of an indexed array.
|
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
|
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
|
`mapfile` returns success (0) unless an invalid option is given or the
|
||||||
given array `ARRAY` is set readonly.
|
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
|
workflow. Xorg updates require rebuilding drivers, and the
|
||||||
Gentoo-suggested command is less than ideal, so let's Bashify it. 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
|
first command produces a list of packages, one per line. We can read
|
||||||
those into the array named \"args\" using `mapfile`, stripping trailing
|
those into the array named "args" using `mapfile`, stripping trailing
|
||||||
newlines with the \'-t\' option. The resulting array is then expanded
|
newlines with the '`-t`' option. The resulting array is then expanded
|
||||||
into the arguments of the \"emerge\" command - an interface to Gentoo's
|
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
|
package manager. This type of usage can make for a safe and effective
|
||||||
replacement for xargs(1) in certain situations. Unlike xargs, all
|
replacement for xargs(1) in certain situations. Unlike xargs, all
|
||||||
arguments are guaranteed to be passed to a single invocation of the
|
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; }
|
# 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
|
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,
|
redirection. This is because the -a flag makes emerge interactive,
|
||||||
asking the user for confirmation before continuing, and checking with
|
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
|
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
|
### The callback
|
||||||
|
|
||||||
This is one of the more unusual features of a Bash builtin. As far as
|
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
|
line is read, the code contained within the string argument to the -C
|
||||||
flag is evaluated and executed *before* the assignment of each array
|
flag is evaluated and executed *before* the assignment of each array
|
||||||
element. There are no restrictions to this string, which can be any
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
because it allows for easy access to the arguments with no ugly "code
|
||||||
in a string\".
|
in a string".
|
||||||
|
|
||||||
$ foo() { echo "|$1|"; }; mapfile -n 11 -c 2 -C 'foo' <file
|
$ foo() { echo "|$1|"; }; mapfile -n 11 -c 2 -C 'foo' <file
|
||||||
|2|
|
|2|
|
||||||
@ -121,13 +121,13 @@ illustrates the callback behavior:
|
|||||||
|
|
||||||
Since redirects are syntactically allowed anywhere in a command, we put
|
Since redirects are syntactically allowed anywhere in a command, we put
|
||||||
it before the printf to stay out of the way of additional arguments.
|
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
|
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
|
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.
|
format specification is used to absorb the index number argument.
|
||||||
|
|
||||||
Another variation might be to add each of these lines to the elements of
|
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
|
reader. This is quite the hack but illustrates some interesting
|
||||||
properties of printf -v and mapfile -C (which you should probably never
|
properties of printf -v and mapfile -C (which you should probably never
|
||||||
use in real code).
|
use in real code).
|
||||||
@ -147,7 +147,7 @@ use in real code).
|
|||||||
|
|
||||||
This example based on yet another #bash question illustrates mapfile in
|
This example based on yet another #bash question illustrates mapfile in
|
||||||
combination with read. The sample input is the heredoc to `main`. The
|
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
|
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 followed by 2 corresponding fields. The showRecord function takes a
|
||||||
key and returns the record.
|
key and returns the record.
|
||||||
|
@ -1,19 +1,22 @@
|
|||||||
# The printf command
|
# The printf command
|
||||||
|
|
||||||
<div center round todo box 70%> FIXME Stranger, this is a very big
|
!!! warning "FIXME"
|
||||||
topic that needs experience - please fill in missing information, extend
|
This is a very big topic that needs experience - please fill in
|
||||||
the descriptions, and correct the details if you can! </div> <div
|
missing information, extend the descriptions, and correct the details
|
||||||
center round tip 70%> [**Attention:**]{.underline} This is about the
|
if you can!
|
||||||
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)
|
!!! info "Bash-Builtin"
|
||||||
expects a comma after the format string and between each of the
|
This is about the Bash-builtin command `printf` - however, the
|
||||||
arguments of a **printf** command. For examples, see: [code
|
description should be nearly identical for an external command that
|
||||||
snippet](../../printf?&.md#using_printf_inside_of_awk). </div>
|
follows POSIX(r).
|
||||||
|
|
||||||
|
[GNU Awk](http://www.gnu.org/software/gawk/manual/gawk.html#Printf)
|
||||||
|
expects a comma after the format string and between each of
|
||||||
|
the arguments of a **printf** command. For examples, see: [code
|
||||||
|
snippet](#differences-from-awk-printf).
|
||||||
|
|
||||||
Unlike other documentations, I don't want to redirect you to the manual
|
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
|
experienced, that should be the most detailed description for the format
|
||||||
strings and modifiers.
|
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:
|
Beside other reasons, POSIX(r) has a very good argument to recommend it:
|
||||||
Both historical main flavours of the `echo` command are mutual
|
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.
|
the issue.
|
||||||
|
|
||||||
## Syntax
|
## Syntax
|
||||||
@ -50,27 +53,28 @@ argument!).
|
|||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
---------- -------------------------------------------------------------------------------------------------------------------------------
|
| 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)
|
|--------|-------------|
|
||||||
---------- -------------------------------------------------------------------------------------------------------------------------------
|
|`-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
|
The `-v` Option can't assign directly to array indexes in Bash versions
|
||||||
older than Bash 4.1.
|
older than Bash 4.1.
|
||||||
|
|
||||||
<note warning> In versions newer than 4.1, one must be careful when
|
!!! danger "Danger"
|
||||||
performing expansions into the first non-option argument of printf as
|
In versions newer than 4.1, one must be careful when
|
||||||
this opens up the possibility of an easy code injection vulnerability.
|
performing expansions into the first non-option argument of printf as
|
||||||
|
this opens up the possibility of an easy code injection vulnerability.
|
||||||
|
|
||||||
$ var='-vx[$(echo hi >&2)]'; printf "$var" hi; declare -p x
|
$ var='-vx[$(echo hi >&2)]'; printf "$var" hi; declare -p x
|
||||||
hi
|
hi
|
||||||
declare -a x='([0]="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
|
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
|
signal the end of options. The exact same issue also applies to
|
||||||
[read](../../commands/builtin/read.md), and a similar one to
|
[read](../../commands/builtin/read.md), and a similar one to
|
||||||
[mapfile](../../commands/builtin/mapfile.md), though performing expansions into
|
[mapfile](../../commands/builtin/mapfile.md), though performing expansions into
|
||||||
their arguments is less common. </note>
|
their arguments is less common.
|
||||||
|
|
||||||
### Arguments
|
### 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
|
common C-notations plus some additions for number-constants are
|
||||||
recognized to give a number-argument to `printf`:
|
recognized to give a number-argument to `printf`:
|
||||||
|
|
||||||
Number-Format Description
|
| Number-Format | Description |
|
||||||
--------------- ------------------------------------------------------------------------------------------------------------------------
|
|----------------|--------------|
|
||||||
`N` A normal decimal number
|
|`N`|A normal decimal number|
|
||||||
`0N` An octal number
|
|`0N`|An octal number|
|
||||||
`0xN` A hexadecimal number
|
|`0xN`|A hexadecimal 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 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**
|
|`'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
|
then the format string is re-used until the last argument is
|
||||||
interpreted. If fewer format specifiers than arguments are present, then
|
interpreted. If fewer format specifiers than arguments are present, then
|
||||||
number-formats are set to zero, while string-formats are set to null
|
number-formats are set to zero, while string-formats are set to null
|
||||||
@ -97,15 +101,15 @@ Take care to avoid [word splitting](../../syntax/expansion/wordsplit.md), as
|
|||||||
accidentally passing the wrong number of arguments can produce wildly
|
accidentally passing the wrong number of arguments can produce wildly
|
||||||
different and unexpected results. See [this article](../../syntax/words.md).
|
different and unexpected results. See [this article](../../syntax/words.md).
|
||||||
|
|
||||||
<note warning> [**Again, attention:**]{.underline} When a numerical
|
!!! danger "Attention"
|
||||||
format expects a number, the internal `printf`-command will use the
|
When a numerical
|
||||||
common Bash arithmetic rules regarding the base. A command like the
|
format expects a number, the internal `printf`-command will use the
|
||||||
following example **will** throw an error, since `08` is not a valid
|
common Bash arithmetic rules regarding the base. A command like the
|
||||||
octal number (`00` to `07`!):
|
following example **will** throw an error, since `08` is not a valid
|
||||||
|
octal number (`00` to `07`!):
|
||||||
|
|
||||||
printf '%d\n' 08
|
printf '%d\n' 08
|
||||||
|
|
||||||
</note>
|
|
||||||
|
|
||||||
### Format strings
|
### 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.
|
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!
|
argument provided!
|
||||||
|
|
||||||
These specifiers have different names, depending who you ask. But they
|
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
|
- format placeholder
|
||||||
- conversion specification
|
- conversion specification
|
||||||
- formatting token
|
- formatting token
|
||||||
- \...
|
- ...
|
||||||
|
|
||||||
Format Description
|
| Format | Description |
|
||||||
-------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|-------------|----------------|
|
||||||
`%b` Print the associated argument while interpreting backslash escapes in there
|
|`%b`|Print the associated argument while interpreting backslash escapes in there|
|
||||||
`%q` Print the associated argument **shell-quoted**, reusable as input
|
|`%q`|Print the associated argument **shell-quoted**, reusable as input|
|
||||||
`%d` Print the associated argument as **signed decimal** number
|
|`%d`|Print the associated argument as **signed decimal** number|
|
||||||
`%i` Same as `%d`
|
|`%i`|Same as `%d`|
|
||||||
`%o` Print the associated argument as **unsigned octal** number
|
|`%o`|Print the associated argument as **unsigned octal** number|
|
||||||
`%u` Print the associated argument as **unsigned decimal** 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`|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)
|
|`%X`|Same as `%x`, but with upper-case hex-digits (A-F)|
|
||||||
`%f` Interpret and print the associated argument as **floating point** number
|
|`%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`|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
|
|`%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`|Interprets the associated argument as **double**, but prints it like `%f` or `%e`
|
||||||
`%G` Same as `%g`, but print it like `%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
|
|`%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
|
|`%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.
|
|`%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`|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`
|
|`%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
|
|`%(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)
|
|`%%`|No conversion is done. Produces a `%` (percent sign)|
|
||||||
|
|
||||||
Some of the mentioned format specifiers can modify their behaviour by
|
Some of the mentioned format specifiers can modify their behaviour by
|
||||||
getting a format modifier:
|
getting a format modifier:
|
||||||
@ -162,26 +166,26 @@ introductory `%` and the character that specifies the format:
|
|||||||
|
|
||||||
#### Field and printing modifiers
|
#### Field and printing modifiers
|
||||||
|
|
||||||
Field output format
|
|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
|
|`<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 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"`
|
|`*`|**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
|
|`#`|"Alternative format" for numbers: see table below|
|
||||||
`-` **Left-bound** text printing in the field (standard is **right-bound**)
|
|`-`|**Left-bound** text printing in the field (standard is **right-bound**)|
|
||||||
`0` Pads numbers with zeros, not spaces
|
|`0`|Pads numbers with zeros, not spaces|
|
||||||
`<space>` Pad a positive number with a space, where a minus (`-`) is for negative numbers
|
|`<space>`|Pad a positive number with a space, where a minus (`-`) is for negative numbers|
|
||||||
`+` Prints all numbers **signed** (`+` for positive, `-` for negative)
|
|`+`|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
|
|`'`|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
|
|Alternative|Format|
|
||||||
-------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|-----------|------|
|
||||||
`%#o` The octal number is printed with a leading zero, unless it's zero itself
|
|`%#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
|
|`%#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)
|
|`%#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
|
|all number formats except `%d`, `%o`, `%x`, `%X`|Always print a decimal point in the output, even if no digits follow it|
|
||||||
|
|
||||||
#### Precision
|
#### 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
|
These are interpreted if used anywhere in the format string, or in an
|
||||||
argument corresponding to a `%b` format.
|
argument corresponding to a `%b` format.
|
||||||
|
|
||||||
Code Description
|
|Code|Description|
|
||||||
---------------- ---------------------------------------------------------------------------------------------------------------------------
|
|----|-----------|
|
||||||
`\\` Prints the character `\` (backslash)
|
|`\\`|Prints the character `\` (backslash)|
|
||||||
`\a` Prints the alert character (ASCII code 7 decimal)
|
|`\a`|Prints the alert character (ASCII code 7 decimal)|
|
||||||
`\b` Prints a backspace
|
|`\b`|Prints a backspace|
|
||||||
`\f` Prints a form-feed
|
|`\f`|Prints a form-feed|
|
||||||
`\n` Prints a newline
|
|`\n`|Prints a newline|
|
||||||
`\r` Prints a carriage-return
|
|`\r`|Prints a carriage-return|
|
||||||
`\t` Prints a horizontal tabulator
|
|`\t`|Prints a horizontal tabulator|
|
||||||
`\v` Prints a vertical tabulator
|
|`\v`|Prints a vertical tabulator|
|
||||||
`\"` Prints a `'`
|
|`\"`|Prints a `'`|
|
||||||
`\?` Prints a `?`
|
|`\?`|Prints a `?`|
|
||||||
`<NNN>` Interprets `<NNN>` as **octal** number and prints the corresponding character from the character set
|
|`<NNN>`|Interprets `<NNN>` as **octal** number and prints the corresponding character from the character set|
|
||||||
`\0<NNN>` same as `<NNN>`
|
|`\0<NNN>`|same as `<NNN>`|
|
||||||
`\x<NNN>` Interprets `<NNN>` as **hexadecimal** number and prints the corresponding character from the character set (**3 digits**)
|
|`\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<NNNN>`|same as `\x<NNN>`, but **4 digits**|
|
||||||
`\U<NNNNNNNN>` same as `\x<NNN>`, but **8 digits**
|
|`\U<NNNNNNNN>`|same as `\x<NNN>`, but **8 digits**|
|
||||||
|
|
||||||
The following additional escape and extra rules apply only to arguments
|
The following additional escape and extra rules apply only to arguments
|
||||||
associated with a `%b` format:
|
associated with a `%b` format:
|
||||||
|
|
||||||
------ -------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|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.
|
|-----------|-----------|
|
||||||
------ -------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|`\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.
|
- Backslashes in the escapes: `\'`, `\"`, and `\?` are not removed.
|
||||||
- Octal escapes beginning with `\0` may contain up to four digits.
|
- 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
|
- octal
|
||||||
- hex
|
- hex
|
||||||
|
|
||||||
```{=html}
|
```bash
|
||||||
<!-- -->
|
for ((x=0; x <= 127; x++)); do
|
||||||
```
|
|
||||||
for ((x=0; x <= 127; x++)); do
|
|
||||||
printf '%3d | %04o | 0x%02x\n' "$x" "$x" "$x"
|
printf '%3d | %04o | 0x%02x\n' "$x" "$x" "$x"
|
||||||
done
|
done
|
||||||
|
```
|
||||||
|
|
||||||
### Ensure well-formatted MAC address
|
### Ensure well-formatted MAC address
|
||||||
|
|
||||||
This code here will take a common MAC address and rewrite it into a
|
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
|
well-known format (regarding leading zeros or upper/lowercase of the hex
|
||||||
digits, \...):
|
digits, ...):
|
||||||
|
|
||||||
the_mac="0:13:ce:7:7a:ad"
|
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,
|
- The a, A, e, E, f, F, g, and G conversions are supported by Bash,
|
||||||
but not required by POSIX.
|
but not required by POSIX.
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
- There is no wide-character support (wprintf). For instance, if you
|
- 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
|
argument. Likewise, the maximum field width modifier (dot) in
|
||||||
combination with `%s` goes by bytes, not characters. This limits
|
combination with `%s` goes by bytes, not characters. This limits
|
||||||
some of printf's functionality to working with ascii only. ksh93's
|
some of printf's functionality to working with ascii only. ksh93's
|
||||||
`printf` supports the `L` modifier with `%s` and `%c` (but so far
|
`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 `%S` or `%C`) in order to treat precision as character width,
|
||||||
not byte count. zsh appears to adjust itself dynamically based upon
|
not byte count. zsh appears to adjust itself dynamically based upon
|
||||||
`LANG` and `LC_CTYPE`. If `LC_CTYPE=C`, zsh will throw \"character
|
`LANG` and `LC_CTYPE`. If `LC_CTYPE=C`, zsh will throw "character
|
||||||
not in range\" errors, and otherwise supports wide characters
|
not in range" errors, and otherwise supports wide characters
|
||||||
automatically if a variable-width encoding is set for the current
|
automatically if a variable-width encoding is set for the current
|
||||||
locale.
|
locale.
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
- Bash recognizes and skips over any characters present in the length
|
- Bash recognizes and skips over any characters present in the length
|
||||||
modifiers specified by POSIX during format string parsing.
|
modifiers specified by POSIX during format string parsing.
|
||||||
|
|
||||||
``` c|builtins/printf.def
|
``` c title="builtins/printf.def"
|
||||||
#define LENMODS "hjlLtz"
|
#define LENMODS "hjlLtz"
|
||||||
...
|
...
|
||||||
/* skip possible format modifiers */
|
/* skip possible format modifiers */
|
||||||
@ -405,7 +402,6 @@ modstart = fmt;
|
|||||||
while (*fmt && strchr (LENMODS, *fmt))
|
while (*fmt && strchr (LENMODS, *fmt))
|
||||||
fmt++;
|
fmt++;
|
||||||
```
|
```
|
||||||
|
|
||||||
- mksh has no built-in printf by default (usually). There is an
|
- mksh has no built-in printf by default (usually). There is an
|
||||||
unsupported compile-time option to include a very poor, basically
|
unsupported compile-time option to include a very poor, basically
|
||||||
unusable implementation. For the most part you must rely upon the
|
unusable implementation. For the most part you must rely upon the
|
||||||
@ -414,19 +410,14 @@ fmt++;
|
|||||||
a new parameter expansion in the form of `${name@Q}` which fills the
|
a new parameter expansion in the form of `${name@Q}` which fills the
|
||||||
role of `printf %q` -- expanding in a shell-escaped format.
|
role of `printf %q` -- expanding in a shell-escaped format.
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
- ksh93 optimizes builtins run from within a command substitution and
|
- ksh93 optimizes builtins run from within a command substitution and
|
||||||
which have no redirections to run in the shell's process. Therefore
|
which have no redirections to run in the shell's process. Therefore
|
||||||
the `printf -v` functionality can be closely matched by
|
the `printf -v` functionality can be closely matched by
|
||||||
`var=$(printf ...)` without a big performance hit.
|
`var=$(printf ...)` without a big performance hit.
|
||||||
|
|
||||||
```{=html}
|
```bash
|
||||||
<!-- -->
|
# Illustrates Bash-like behavior. Redefining printf is usually unnecessary / not recommended.
|
||||||
```
|
function printf {
|
||||||
# Illustrates Bash-like behavior. Redefining printf is usually unnecessary / not recommended.
|
|
||||||
function printf {
|
|
||||||
case $1 in
|
case $1 in
|
||||||
-v)
|
-v)
|
||||||
shift
|
shift
|
||||||
@ -437,13 +428,14 @@ fmt++;
|
|||||||
*)
|
*)
|
||||||
command printf "$@"
|
command printf "$@"
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
builtin cut
|
builtin cut
|
||||||
print $$
|
print $$
|
||||||
printf -v 'foo[2]' '%d\n' "$(cut -d ' ' -f 1 /proc/self/stat)"
|
printf -v 'foo[2]' '%d\n' "$(cut -d ' ' -f 1 /proc/self/stat)"
|
||||||
typeset -p foo
|
typeset -p foo
|
||||||
# 22461
|
# 22461
|
||||||
# typeset -a foo=([2]=22461)
|
# typeset -a foo=([2]=22461)
|
||||||
|
```
|
||||||
|
|
||||||
- The optional Bash loadable `print` may be useful for ksh
|
- The optional Bash loadable `print` may be useful for ksh
|
||||||
compatibility and to overcome some of
|
compatibility and to overcome some of
|
||||||
@ -455,10 +447,6 @@ fmt++;
|
|||||||
only `-Rrnfu` are actually functional. Internally, `-p` is a noop
|
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
|
(it doesn't tie in with Bash coprocs at all), and `-s` only sets a
|
||||||
flag but has no effect. `-Cev` are unimplemented.
|
flag but has no effect. `-Cev` are unimplemented.
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
- Assigning to variables: The `printf -v` way is slightly different to
|
- Assigning to variables: The `printf -v` way is slightly different to
|
||||||
the way using command-substitution. [Command
|
the way using command-substitution. [Command
|
||||||
substitution](../../syntax/expansion/cmdsubst.md) removes trailing newlines
|
substitution](../../syntax/expansion/cmdsubst.md) removes trailing newlines
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
## Description
|
## 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
|
from standard input or a supplied filedescriptor number into one or more
|
||||||
variables named by `<NAME...>`.
|
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
|
`-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
|
`-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!)
|
`-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)
|
`-u <FD>` use the filedescriptor number `<FD>` rather than `stdin` (0)
|
||||||
|
|
||||||
When both, `-a <ARRAY>` and a variable name `<NAME>` is given, then the
|
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"
|
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.
|
because we want to have the real literal line, without any mangeling.
|
||||||
`printf` is used, because (depending on settings), `echo` may interpret
|
`printf` is used, because (depending on settings), `echo` may interpret
|
||||||
some baskslash-escapes or switches (like `-n`).
|
some baskslash-escapes or switches (like `-n`).
|
||||||
|
|
||||||
### Press any key\...
|
### Press any key...
|
||||||
|
|
||||||
Remember the MSDOS `pause` command? Here's something similar:
|
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
|
### 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
|
read -e -p "Enter the path to the file: " -i "/usr/local/etc/" FILEPATH
|
||||||
|
|
||||||
|
@ -15,23 +15,23 @@ readonly variables.
|
|||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
Option Description
|
|Option|Description|
|
||||||
-------- ------------------------------------------------------------------------------------------------------------------------
|
|-|-|
|
||||||
`-a` refer to normal arrays
|
|`-a`|refer to normal arrays|
|
||||||
`-A` refer to associative arrays
|
|`-A`|refer to associative arrays|
|
||||||
`-f` refer to functions
|
|`-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
|
|`-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.
|
An argument of `--` disables further option processing.
|
||||||
|
|
||||||
### Return status
|
### Return status
|
||||||
|
|
||||||
Status Reason
|
|Status|Reason|
|
||||||
-------- --------------------------------
|
|-|-|
|
||||||
0 no error
|
|0|no error|
|
||||||
!=0 invalid option
|
|!=0|invalid option|
|
||||||
!=0 invalid combination of options
|
|!=0|invalid combination of options|
|
||||||
!=0 a given `NAME` is invalid
|
|!=0|a given `NAME` is invalid|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
@ -21,9 +21,9 @@ There are no options.
|
|||||||
If everything is okay, the `return` command doesn't come back. If it
|
If everything is okay, the `return` command doesn't come back. If it
|
||||||
comes back, there was a problem in doing the return.
|
comes back, there was a problem in doing the return.
|
||||||
|
|
||||||
Status Reason
|
|Status|Reason|
|
||||||
-------- -------------------------------------------------------------------------
|
|-|-|
|
||||||
1 `return` was called while not being in a shell function or sourced file
|
|1|`return` was called while not being in a shell function or sourced file|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# The set builtin command
|
# The set builtin command
|
||||||
|
|
||||||
FIXME incomplete - text, examples, maybe extended description
|
!!! warning "FIXME"
|
||||||
|
incomplete text, examples, maybe extended description
|
||||||
|
|
||||||
## Synopsis
|
## 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
|
using `+X`. This is done because of the historical meaning of the `-` to
|
||||||
set flags (true for most commands on UNIX(r)).
|
set flags (true for most commands on UNIX(r)).
|
||||||
|
|
||||||
Flag Optionname Description
|
|Flag|Optionname|Description|
|
||||||
------ ---------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|----|----------|-----------|
|
||||||
`-a` `allexport` Automatically mark new and altered variables to be exported to subsequent environments.
|
|`-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)
|
|`-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`, `||`, `&&`)
|
|`-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)
|
|`-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.
|
|`-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.
|
|`-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).
|
|`-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.
|
|`-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.
|
|`-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.
|
|`-p`|`privileged`|Turn on privileged mode.|
|
||||||
`-t` `onecmd` Exit after reading and executing **one** command.
|
|`-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.
|
|`-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.
|
|`-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.
|
|`-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.
|
|`-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)
|
|`-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.
|
|`-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.
|
|`-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.
|
|`-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.
|
|`-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.
|
|`-`||"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.
|
|`--`||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
|
|**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.
|
||`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)
|
||`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).
|
||`ignoreeof`|The effect is as if the shell command `IGNOREEOF=10` had been executed. See [shell variables](../../syntax/shellvars.md).|
|
||||||
`nolog` **(currently ignored)**
|
||`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)
|
||`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.
|
||`posix`|When set, Bash runs in POSIX mode.|
|
||||||
`vi` Enables a `vi`-style command line editing interface.
|
||`vi`|Enables a `vi`-style command line editing interface.|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
## Description
|
## 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.
|
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
|
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`):
|
Imagine the following set of positional parameters (`$1` to `$4`):
|
||||||
|
|
||||||
1 This
|
|Positional Parameter|Value|
|
||||||
--- ------
|
|-|-|
|
||||||
2 is
|
|1|This
|
||||||
3 a
|
|2|is|
|
||||||
4 test
|
|3|a|
|
||||||
|
|4|test|
|
||||||
|
|
||||||
When you use `shift 1`, they will be changed to:
|
When you use `shift 1`, they will be changed to:
|
||||||
|
|
||||||
1 is
|
|Positional Parameter|Value|
|
||||||
--- ------
|
|-|-|
|
||||||
2 a
|
|1|is|
|
||||||
3 test
|
|2|a|
|
||||||
|
|3|test|
|
||||||
|
|
||||||
The [special parameter](../../syntax/shellvars.md#special_parameters) `$#` will
|
The [special parameter](../../syntax/shellvars.md#special_parameters) `$#` will
|
||||||
reflect the final number of positional parameters.
|
reflect the final number of positional parameters.
|
||||||
@ -40,12 +42,12 @@ There are no options.
|
|||||||
|
|
||||||
### Return status
|
### Return status
|
||||||
|
|
||||||
Status Reason
|
|Status|Reason|
|
||||||
-------- -----------------------------------------------------------------------------------------------------
|
|------|------|
|
||||||
0 no error
|
|0|no error|
|
||||||
1 non-numeric argument
|
|1|non-numeric argument|
|
||||||
1 given number (or the default 1) is bigger than the number of actually present positional parameters
|
|1|given number (or the default 1) is bigger than the number of actually present positional parameters|
|
||||||
1 given number is negative
|
|1|given number is negative|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
@ -59,30 +61,37 @@ There are no options.
|
|||||||
[shift_verbose](../../internals/shell_options.md#shift_verbose)
|
[shift_verbose](../../internals/shell_options.md#shift_verbose)
|
||||||
[shopt](../../commands/builtin/shopt.md) option is enabled. Ksh93, pdksh,
|
[shopt](../../commands/builtin/shopt.md) option is enabled. Ksh93, pdksh,
|
||||||
posh, mksh, and dash, all throw useless fatal shell
|
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
|
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
|
`command` builtin to suppress fatal
|
||||||
errors caused by *special builtins*. <code> \$ dash -c \'f() { if
|
errors caused by *special builtins*.
|
||||||
command shift 2>/dev/null; then echo \"\$1\"; else echo \"no
|
```
|
||||||
args\"; fi; }; f\'
|
$ dash -c 'f() { if command shift 2>/dev/null; then echo "$1"; else echo "no args"; fi; }; f'
|
||||||
|
no args
|
||||||
no args </code> While, POSIX requires this behavior, it isn't very
|
```
|
||||||
|
While, POSIX requires this behavior, it isn't very
|
||||||
obvious and some shells don't do it correctly. To work around this, you
|
obvious and some shells don't do it correctly. To work around this, you
|
||||||
can use something like:
|
can use something like:
|
||||||
|
```
|
||||||
<code> \$ mksh -c \'f() { if ! \${1+false} && shift; then echo
|
$ mksh -c 'f() { if ! ${1+false} && shift; then echo "$1"; else echo "no args"; fi; }; f'
|
||||||
\"\$1\"; else echo \"no args\"; fi; }; f\' no args </code> ~~The mksh
|
no args
|
||||||
maintainer refuses to change either the `shift` or `command` builtins.~~
|
```
|
||||||
|
<del>The mksh maintainer refuses to change either the `shift` or `command` builtins.</del>
|
||||||
[Fixed](https://github.com/MirBSD/mksh/commit/996e05548ab82f7ef2dea61f109cc7b6d13837fa).
|
[Fixed](https://github.com/MirBSD/mksh/commit/996e05548ab82f7ef2dea61f109cc7b6d13837fa).
|
||||||
(Thanks!)
|
(Thanks!)
|
||||||
|
|
||||||
- Perhaps almost as bad as the above, busybox sh's `shift` always
|
- Perhaps almost as bad as the above, busybox sh's `shift` always
|
||||||
returns success, even when attempting to shift beyond the final
|
returns success, even when attempting to shift beyond the final
|
||||||
argument. <code> \$ bb -c \'f() { if shift; then echo \"\$1\";
|
argument.
|
||||||
else echo \"no args\"; fi; }; f\'
|
```
|
||||||
|
$ 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
|
(no output)
|
||||||
|
```
|
||||||
|
The above mksh workaround will work in this case
|
||||||
too.
|
too.
|
||||||
|
|
||||||
## See also
|
## See also
|
||||||
|
@ -15,13 +15,13 @@ Note: Some of these options and other shell options can also be set with
|
|||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
Option Description
|
|Option|Description|
|
||||||
-------- -----------------------------------------------------------------------------------------------------------------------------
|
|------|-----------|
|
||||||
`-o` Restrict the values of `<OPTNAME...>` to only those also known by [the set builtin](../../commands/builtin/set.md)
|
|`-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**.
|
|`-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
|
|`-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
|
|`-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]{.underline}nset) the shell options named by `<OPTNAME...>` or list all *disabled* 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,
|
As noted above, if only `-s` or `-u` are given without any option names,
|
||||||
only the currently enabled (`-s`) or disabled (`-u`) options are
|
only the currently enabled (`-s`) or disabled (`-u`) options are
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|
||||||
The `trap` command is used to \"trap\" signals and other events. In this
|
The `trap` command is used to "trap" signals and other events. In this
|
||||||
context, \"trapping\" means to install handler code.
|
context, "trapping" means to install handler code.
|
||||||
|
|
||||||
The shell code `ARGUMENT` is to be read and executed whenever the shell
|
The shell code `ARGUMENT` is to be read and executed whenever the shell
|
||||||
receives a signal or another event `SIGNAL`. The given `SIGNAL`
|
receives a signal or another event `SIGNAL`. The given `SIGNAL`
|
||||||
@ -29,27 +29,27 @@ Special `ARGUMENT`s
|
|||||||
|
|
||||||
Special events
|
Special events
|
||||||
|
|
||||||
Name Code Description
|
|Name|Code|Description|
|
||||||
---------- ------ --------------------------------------------------------------------------------------------------------------------------------------------
|
|----|----|-----------|
|
||||||
`EXIT` 0 executed on shell exit
|
|`EXIT`|0|executed on shell exit|
|
||||||
`DEBUG` executed before every simple command
|
|`DEBUG`||executed before every simple command|
|
||||||
`RETURN` executed when a shell function or a sourced code finishes executing
|
|`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
|
|`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
|
### Options
|
||||||
|
|
||||||
Option Description
|
|Option|Description|
|
||||||
-------- ------------------------------------------------------------------------------------------
|
|------|-----------|
|
||||||
`-l` print a list of signal names and their corresponding numbers
|
|`-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
|
|`-p`|display the trap commands associated with each signal specification in a reusable format|
|
||||||
|
|
||||||
### Return status
|
### Return status
|
||||||
|
|
||||||
Status Reason
|
|Status|Reason|
|
||||||
-------- ------------------------------
|
|------|------|
|
||||||
0 no error/success
|
|0|no error/success|
|
||||||
!=0 invalid option
|
|!=0|invalid option|
|
||||||
!=0 invalid signal specification
|
|!=0|invalid signal specification|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
@ -12,20 +12,20 @@ unset a variable first, then a function.
|
|||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
Option Description
|
|Option|Description|
|
||||||
-------- --------------------------------------------------------------------------------------------------------------
|
|------|-----------|
|
||||||
`-f` treats each `NAME` as a function name
|
|`-f`|treats each `NAME` as a function name|
|
||||||
`-v` treats each `NAME` as a variable 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
|
|`-n`|treats each `NAME` as a name reference and unsets the variable itself rather than the variable it references|
|
||||||
|
|
||||||
### Exit status
|
### Exit status
|
||||||
|
|
||||||
Status Reason
|
|Status|Reason|
|
||||||
-------- ----------------------------------------------------
|
|------|------|
|
||||||
0 no error
|
|0|no error|
|
||||||
!=0 invalid option
|
|!=0|invalid option|
|
||||||
!=0 invalid combination of options (`-v` **and** `-f`)
|
|!=0|invalid combination of options (`-v` **and** `-f`)|
|
||||||
!=0 a given `NAME` is read-only
|
|!=0|a given `NAME` is read-only|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
@ -123,7 +123,7 @@ Some things to observe:
|
|||||||
- `unset2` is only really needed once. We remain 5 levels deep in
|
- `unset2` is only really needed once. We remain 5 levels deep in
|
||||||
`f`'s for the remaining `unset` calls, which peel away the outer
|
`f`'s for the remaining `unset` calls, which peel away the outer
|
||||||
layers of `a`'s.
|
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
|
recursion depth 1, and subsequently calling unset reveals a again in
|
||||||
the global scope, which has since been modified in a lower scope
|
the global scope, which has since been modified in a lower scope
|
||||||
using declare -g.
|
using declare -g.
|
||||||
@ -133,7 +133,7 @@ Some things to observe:
|
|||||||
- This doesn't apply to individual array elements. If two local
|
- This doesn't apply to individual array elements. If two local
|
||||||
arrays of the same name appear in different scopes, the entire array
|
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
|
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,
|
identical for individual array elements, and for arrays as a whole,
|
||||||
unset and unset2 behave as they do for scalar variables.
|
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
|
- waits for a specific job (asynchronous command) and report its exit
|
||||||
status if one or more `ID` is given
|
status if one or more `ID` is given
|
||||||
- waits for all running jobs (asynchronous commands)
|
- 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)
|
- waits for termination instead of status change (`-f` option)
|
||||||
|
|
||||||
`ID` may be an operating system process identifier or a shell job
|
`ID` may be an operating system process identifier or a shell job
|
||||||
@ -22,20 +22,20 @@ specification.
|
|||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
Option Description
|
|Option|Description|
|
||||||
-------------- ---------------------------------------------------------------------------------------------------------------------------------
|
|------|-----------|
|
||||||
`-n` Waits for \"the next\" child to exit (as opposed to \"all children\" without this option). Accepts a list of IDs (jobs)
|
|`-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)
|
|`-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`
|
|`-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
|
### Return status
|
||||||
|
|
||||||
The return status is the return status of the job waited for, or
|
The return status is the return status of the job waited for, or
|
||||||
|
|
||||||
Status Reason
|
|Status|Reason|
|
||||||
-------- -------------------------------------------------
|
|------|------|
|
||||||
0 waited for all jobs in shell's job list
|
|0|waited for all jobs in shell's job list|
|
||||||
1 the given `ID` is not a valid job or process ID
|
|1|the given `ID` is not a valid job or process ID|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# Parameter
|
# Parameter
|
||||||
|
|
||||||
Also the article for: [variable]{.underline}, [positional
|
Also the article for: <u>variable</u>, <u>positional
|
||||||
parameter]{.underline}, [special parameter]{.underline}
|
parameter</u>, <u>special parameter</u>
|
||||||
|
|
||||||
In Bash, a parameter is simply an entity that stores values and can be
|
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,
|
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
|
and flow control around the possibility to execute commands - it's a
|
||||||
complete commandline-oriented user-interface (UI).
|
complete commandline-oriented user-interface (UI).
|
||||||
|
|
||||||
FIXME
|
!!! warning "FIXME"
|
||||||
|
tbd.
|
||||||
|
|
||||||
## See also
|
## See also
|
||||||
|
|
||||||
|
@ -12,9 +12,9 @@ tags:
|
|||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
dc(1) is a non standard, but commonly found, reverse-polish Desk
|
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
|
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
|
Historically the standard bc(1) has been implemented as a *front-end to
|
||||||
dc*.
|
dc*.
|
||||||
@ -26,15 +26,15 @@ stack first, then an operation is applied to them. Instead of writing
|
|||||||
`1+1`, you write `1 1+`.
|
`1+1`, you write `1 1+`.
|
||||||
|
|
||||||
By default `dc`, unlike `bc`, doesn't print anything, the result is
|
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:
|
element at the top of the stack. Thus a simple operation looks like:
|
||||||
|
|
||||||
$ dc <<< '1 1+pq'
|
$ dc <<< '1 1+pq'
|
||||||
2
|
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
|
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.
|
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
|
## Scale And Base
|
||||||
|
|
||||||
`dc` is a calulator with abitrary precision, by default this precision
|
`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
|
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:
|
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
|
- `d` duplicates the top of the stack
|
||||||
- `c` clears the stack
|
- `c` clears the stack
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
$ dc << EOF
|
$ dc << EOF
|
||||||
2 # put 2 on the stack
|
2 # put 2 on the stack
|
||||||
d # duplicate i.e. put another 2 on the stack
|
d # duplicate i.e. put another 2 on the stack
|
||||||
@ -228,7 +225,7 @@ we are used to reading:
|
|||||||
EOF
|
EOF
|
||||||
|
|
||||||
Some `dc` have `>R <R =R`, GNU `dc` had some more, check your manual.
|
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
|
popped off the stack (you can verify that
|
||||||
`dc <<< "[f]sR 2 1 >R 1 2 >R f"` doesn't print anything)
|
`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 <<< '[lip1-si0li>L]sL10silLx'
|
||||||
dc <<< '[p1-d0<L]sL10lLx' # use the stack instead of a register
|
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.
|
stack instead of a register for the index.
|
||||||
|
|
||||||
## Next
|
## Next
|
||||||
|
|
||||||
Check your dc manual, i haven't decribed everything, like arrays (only
|
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*
|
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
|
results in //Segmentation Fault (core dump) //, the latest solaris uses
|
||||||
GNU dc)
|
GNU dc)
|
||||||
|
@ -10,7 +10,7 @@ tags:
|
|||||||
|
|
||||||
# Collapsing Functions
|
# Collapsing Functions
|
||||||
|
|
||||||
## What is a \"Collapsing Function\"?
|
## What is a "Collapsing Function"?
|
||||||
|
|
||||||
A collapsing function is a function whose behavior changes depending
|
A collapsing function is a function whose behavior changes depending
|
||||||
upon the circumstances under which it's run. Function collapsing is
|
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
|
Function collapsing requires some static feature in the environment. A
|
||||||
common example is a script that gives the user the option of having
|
common example is a script that gives the user the option of having
|
||||||
\"verbose\" output.
|
"verbose" output.
|
||||||
|
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
@ -49,20 +49,22 @@ common example is a script that gives the user the option of having
|
|||||||
## How does it work?
|
## How does it work?
|
||||||
|
|
||||||
The first time you run chatter(), the function redefines itself based on
|
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.
|
simply is. Further calls to the function reflect its collapsed nature.
|
||||||
If verbose is unset, chatter will echo nothing, with no extra effort
|
If verbose is unset, chatter will echo nothing, with no extra effort
|
||||||
from the developer.
|
from the developer.
|
||||||
|
|
||||||
## More examples
|
## More examples
|
||||||
|
|
||||||
FIXME Add more examples!
|
!!! warning "FIXME"
|
||||||
|
Add more examples!
|
||||||
|
|
||||||
# Somewhat more portable find -executable
|
```bash
|
||||||
# FIXME/UNTESTED (I don't have access to all of the different versions of find.)
|
# Somewhat more portable find -executable
|
||||||
# Usage: find PATH ARGS -- use find like normal, except use -executable instead of
|
# FIXME/UNTESTED (I don't have access to all of the different versions of find.)
|
||||||
# various versions of -perm /+ blah blah and hacks
|
# Usage: find PATH ARGS -- use find like normal, except use -executable instead of
|
||||||
find() {
|
# various versions of -perm /+ blah blah and hacks
|
||||||
|
find() {
|
||||||
hash find || { echo 'find not found!'; exit 1; }
|
hash find || { echo 'find not found!'; exit 1; }
|
||||||
# We can be pretty sure "$0" should be executable.
|
# We can be pretty sure "$0" should be executable.
|
||||||
if [[ $(command find "$0" -executable 2> /dev/null) ]]; then
|
if [[ $(command find "$0" -executable 2> /dev/null) ]]; then
|
||||||
@ -93,14 +95,17 @@ FIXME Add more examples!
|
|||||||
}
|
}
|
||||||
fi
|
fi
|
||||||
find "$@"
|
find "$@"
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
#!/bin/bash
|
```bash
|
||||||
# Using collapsing functions to turn debug messages on/off
|
#!/bin/bash
|
||||||
|
# Using collapsing functions to turn debug messages on/off
|
||||||
|
|
||||||
[ "--debug" = "$1" ] && dbg=echo || dbg=:
|
[ "--debug" = "$1" ] && dbg=echo || dbg=:
|
||||||
|
|
||||||
|
|
||||||
# From now on if you use $dbg instead of echo, you can select if messages will be shown
|
# From now on if you use $dbg instead of echo, you can select if messages will be shown
|
||||||
|
|
||||||
$dbg "This message will only be displayed if --debug is specified at the command line
|
$dbg "This message will only be displayed if --debug is specified at the command line
|
||||||
|
```
|
||||||
|
@ -16,7 +16,7 @@ tags:
|
|||||||
For this task, you don't have to write large parser routines (unless
|
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
|
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
|
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
|
#!/bin/bash
|
||||||
echo "Reading config...." >&2
|
echo "Reading config...." >&2
|
||||||
@ -50,7 +50,7 @@ usage of the dot is identical:
|
|||||||
## Per-user configs
|
## Per-user configs
|
||||||
|
|
||||||
There's also a way to provide a system-wide config file in /etc and a
|
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
|
the following example, the if/then construct is used to check for the
|
||||||
existance of a user-specific config:
|
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
|
As mentioned earlier, the sourced file can contain anything a Bash
|
||||||
script can. Essentially, it **is** an included Bash script. That creates
|
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
|
your script is sourcing its config file. You might want to allow only
|
||||||
constructs in the form `NAME=VALUE` in that file (variable assignment
|
constructs in the form `NAME=VALUE` in that file (variable assignment
|
||||||
syntax) and maybe comments (though technically, comments are
|
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:
|
malicious code:
|
||||||
|
|
||||||
# cool config file for my even cooler script
|
# 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
|
# now source it, either the original or the filtered variant
|
||||||
source "$configfile"
|
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
|
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
|
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
|
name is changed to the name stored in the variable `configfile`. The
|
||||||
|
@ -1,36 +1,36 @@
|
|||||||
# Dissect a bad oneliner
|
# Dissect a bad oneliner
|
||||||
|
|
||||||
``` bash
|
```bash
|
||||||
$ ls *.zip | while read i; do j=`echo $i | sed 's/.zip//g'`; mkdir $j; cd $j; unzip ../$i; cd ..; done
|
$ ls *.zip | while read i; do j=`echo $i | sed 's/.zip//g'`; mkdir $j; cd $j; unzip ../$i; cd ..; done
|
||||||
```
|
```
|
||||||
|
|
||||||
This is an actual one-liner someone asked about in `#bash`. **There are
|
This is an actual one-liner someone asked about in `#bash`. **There are
|
||||||
several things wrong with it. Let's break it down!**
|
several things wrong with it. Let's break it down!**
|
||||||
|
|
||||||
``` bash
|
```bash
|
||||||
$ ls *.zip | while read i; do ...; done
|
$ ls *.zip | while read i; do ...; done
|
||||||
```
|
```
|
||||||
|
|
||||||
(Please read <http://mywiki.wooledge.org/ParsingLs>.) This command
|
(Please read <http://mywiki.wooledge.org/ParsingLs>.) This command
|
||||||
executes `ls` on the expansion of `*.zip`. Assuming there are filenames
|
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.
|
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:
|
But in sh and bash alike, we can loop safely over the glob itself:
|
||||||
|
|
||||||
``` bash
|
```bash
|
||||||
$ for i in *.zip; do j=`echo $i | sed 's/.zip//g'`; mkdir $j; cd $j; unzip ../$i; cd ..; done
|
$ for i in *.zip; do j=`echo $i | sed 's/.zip//g'`; mkdir $j; cd $j; unzip ../$i; cd ..; done
|
||||||
```
|
```
|
||||||
|
|
||||||
Let's break it down some more!
|
Let's break it down some more!
|
||||||
|
|
||||||
``` bash
|
```bash
|
||||||
j=`echo $i | sed 's/.zip//g'` # where $i is some name ending in '.zip'
|
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.
|
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`
|
In fact, there is a POSIX(r)-compliant command to do this: `basename`
|
||||||
The implementation here is suboptimal in several ways, but the only
|
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
|
an *unquoted* variable means
|
||||||
[wordsplitting](../syntax/expansion/wordsplit.md) will take place, so any
|
[wordsplitting](../syntax/expansion/wordsplit.md) will take place, so any
|
||||||
whitespace in `$i` will essentially be normalized. In `sh` it is
|
whitespace in `$i` will essentially be normalized. In `sh` it is
|
||||||
@ -41,7 +41,7 @@ performance in a loop). Just for good measure, let's use the more
|
|||||||
readable, [modern](../syntax/expansion/cmdsubst.md) `$()` construct instead
|
readable, [modern](../syntax/expansion/cmdsubst.md) `$()` construct instead
|
||||||
of the old style backticks:
|
of the old style backticks:
|
||||||
|
|
||||||
``` bash
|
```bash
|
||||||
sh $ for i in *.zip; do j=$(basename "$i" ".zip"); mkdir $j; cd $j; unzip ../$i; cd ..; done
|
sh $ for i in *.zip; do j=$(basename "$i" ".zip"); mkdir $j; cd $j; unzip ../$i; cd ..; done
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -49,27 +49,27 @@ In Bash we don't need the subshell or the external basename command.
|
|||||||
See [Substring removal with parameter
|
See [Substring removal with parameter
|
||||||
expansion](../syntax/pe.md#substring_removal):
|
expansion](../syntax/pe.md#substring_removal):
|
||||||
|
|
||||||
``` bash
|
```bash
|
||||||
bash $ for i in *.zip; do j="${i%.zip}"; mkdir $j; cd $j; unzip ../$i; cd ..; done
|
bash $ for i in *.zip; do j="${i%.zip}"; mkdir $j; cd $j; unzip ../$i; cd ..; done
|
||||||
```
|
```
|
||||||
|
|
||||||
Let's keep going:
|
Let's keep going:
|
||||||
|
|
||||||
``` bash
|
```bash
|
||||||
$ mkdir $j; cd $j; ...; cd ..
|
$ mkdir $j; cd $j; ...; cd ..
|
||||||
```
|
```
|
||||||
|
|
||||||
As a programmer, you **never** know the situation under which your
|
As a programmer, you **never** know the situation under which your
|
||||||
program will run. Even if you do, the following best practice will never
|
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
|
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
|
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
|
to execute the following command(s). It's fully POSIX(r). Oh, and
|
||||||
remember what I said about [wordsplitting](../syntax/expansion/wordsplit.md)
|
remember what I said about [wordsplitting](../syntax/expansion/wordsplit.md)
|
||||||
in the previous step? Well, if you don't quote `$j`, wordsplitting can
|
in the previous step? Well, if you don't quote `$j`, wordsplitting can
|
||||||
happen again.
|
happen again.
|
||||||
|
|
||||||
``` bash
|
```bash
|
||||||
$ mkdir "$j" && cd "$j" && ... && cd ..
|
$ mkdir "$j" && cd "$j" && ... && cd ..
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -78,47 +78,47 @@ contains a slash? Then `cd ..` will not return to the original
|
|||||||
directory. That's wrong! `cd -` causes cd to return to the previous
|
directory. That's wrong! `cd -` causes cd to return to the previous
|
||||||
working directory, so it's a much better choice:
|
working directory, so it's a much better choice:
|
||||||
|
|
||||||
``` bash
|
```bash
|
||||||
$ mkdir "$j" && cd "$j" && ... && cd -
|
$ mkdir "$j" && cd "$j" && ... && cd -
|
||||||
```
|
```
|
||||||
|
|
||||||
(If it occurred to you that I forgot to check for success after 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
|
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
|
will be able to get back to our original working directory without a
|
||||||
problem.)
|
problem.)
|
||||||
|
|
||||||
So now we have:
|
So now we have:
|
||||||
|
|
||||||
``` bash
|
```bash
|
||||||
sh $ for i in *.zip; do j=$(basename "$i" ".zip"); mkdir "$j" && cd "$j" && unzip ../$i && cd -; done
|
sh $ for i in *.zip; do j=$(basename "$i" ".zip"); mkdir "$j" && cd "$j" && unzip ../$i && cd -; done
|
||||||
```
|
```
|
||||||
|
|
||||||
``` bash
|
```bash
|
||||||
bash $ for i in *.zip; do j="${i%.zip}"; mkdir "$j" && cd "$j" && unzip ../$i && cd -; done
|
bash $ for i in *.zip; do j="${i%.zip}"; mkdir "$j" && cd "$j" && unzip ../$i && cd -; done
|
||||||
```
|
```
|
||||||
|
|
||||||
Let's throw the `unzip` command back in the mix:
|
Let's throw the `unzip` command back in the mix:
|
||||||
|
|
||||||
``` bash
|
```bash
|
||||||
mkdir "$j" && cd "$j" && unzip ../$i && cd -
|
mkdir "$j" && cd "$j" && unzip ../$i && cd -
|
||||||
```
|
```
|
||||||
|
|
||||||
Well, besides word splitting, there's nothing terribly wrong with this.
|
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
|
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
|
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:
|
the cd commands entirely:
|
||||||
|
|
||||||
``` bash
|
```bash
|
||||||
$ mkdir "$j" && unzip -d "$j" "$i"
|
$ mkdir "$j" && unzip -d "$j" "$i"
|
||||||
```
|
```
|
||||||
|
|
||||||
``` bash
|
```bash
|
||||||
sh $ for i in *.zip; do j=$(basename "$i" ".zip"); mkdir "$j" && unzip -d "$j" "$i"; done
|
sh $ for i in *.zip; do j=$(basename "$i" ".zip"); mkdir "$j" && unzip -d "$j" "$i"; done
|
||||||
```
|
```
|
||||||
|
|
||||||
``` bash
|
```bash
|
||||||
bash $ for i in *.zip; do j="${i%.zip}"; mkdir "$j" && unzip -d "$j" "$i"; done
|
bash $ for i in *.zip; do j="${i%.zip}"; mkdir "$j" && unzip -d "$j" "$i"; done
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -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
|
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
|
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
|
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`?
|
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
|
that come from `stdin`. There are several ways to feed our commands to
|
||||||
ed:
|
ed:
|
||||||
|
|
||||||
**[Pipelines]{.underline}**
|
**<u>Pipelines</u>**
|
||||||
|
|
||||||
echo '<ED-COMMANDS>' | ed <FILE>
|
echo '<ED-COMMANDS>' | ed <FILE>
|
||||||
|
|
||||||
To inject the needed newlines, etc. it may be easier to use the builtin
|
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:
|
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"
|
printf '%s\n' H 1i "$1" . w | ed -s "$2"
|
||||||
}
|
}
|
||||||
|
|
||||||
**[Here-strings]{.underline}**
|
**<u>Here-strings</u>**
|
||||||
|
|
||||||
ed <FILE> <<< '<ED-COMMANDS>'
|
ed <FILE> <<< '<ED-COMMANDS>'
|
||||||
|
|
||||||
**[Here-documents]{.underline}**
|
**<u>Here-documents</u>**
|
||||||
|
|
||||||
ed <FILE> <<EOF
|
ed <FILE> <<EOF
|
||||||
<ED-COMMANDS>
|
<ED-COMMANDS>
|
||||||
@ -71,17 +71,17 @@ it looks best here IMHO.
|
|||||||
There are other ways to provide input to `ed`. For example, process
|
There are other ways to provide input to `ed`. For example, process
|
||||||
substitution. But these should be enough for daily needs.
|
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
|
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.
|
`-s` option to make it less verbose.
|
||||||
|
|
||||||
## The basic interface
|
## The basic interface
|
||||||
|
|
||||||
Check the `ed` manpage for details
|
Check the `ed` manpage for details
|
||||||
|
|
||||||
Similar to `vi` or `vim`, `ed` has a \"command mode\" and an
|
Similar to `vi` or `vim`, `ed` has a "command mode" and an
|
||||||
\"interactive mode\". For non-interactive use, the command mode is the
|
"interactive mode". For non-interactive use, the command mode is the
|
||||||
usual choice.
|
usual choice.
|
||||||
|
|
||||||
Commands to `ed` have a simple and regular structure: zero, one, or two
|
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
|
## 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
|
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
|
short message explaining the last error. You can also turn on a mode
|
||||||
that makes `ed` automatically print this message with the `H` command.
|
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'
|
ed -s test.txt <<< $',s/Windows(R)-compatible/POSIX-conform/g\nw'
|
||||||
|
|
||||||
[Note:]{.underline} The comma as single address operator is an alias for
|
<u>Note:</u> The comma as single address operator is an alias for
|
||||||
`1,$` (\"all lines\").
|
`1,$` ("all lines").
|
||||||
|
|
||||||
#### Substitutions in specific lines
|
#### Substitutions in specific lines
|
||||||
|
|
||||||
@ -188,7 +188,7 @@ regexp
|
|||||||
|
|
||||||
#### Move a block of text
|
#### 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.
|
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
|
#### 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.
|
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
|
#### 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).
|
command: `j` (join).
|
||||||
|
|
||||||
ed -s file <<< $'1,$j\nw'
|
ed -s file <<< $'1,$j\nw'
|
||||||
@ -272,7 +272,7 @@ about it with the g (global) command:
|
|||||||
**\_\_ an error stops the script \_\_**
|
**\_\_ an error stops the script \_\_**
|
||||||
|
|
||||||
You might think that it's not a problem and that the same thing happens
|
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.
|
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
|
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
|
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 \_\_**
|
**\_\_ 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
|
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
|
#fails
|
||||||
ed -s file << EOF
|
ed -s file << EOF
|
||||||
@ -313,7 +313,7 @@ obvious but it's easy to forget this fact when you use addresses like
|
|||||||
|
|
||||||
#ok
|
#ok
|
||||||
ed -s file << EOF
|
ed -s file << EOF
|
||||||
\$a
|
$a
|
||||||
last line
|
last line
|
||||||
.
|
.
|
||||||
w
|
w
|
||||||
@ -327,9 +327,9 @@ obvious but it's easy to forget this fact when you use addresses like
|
|||||||
w
|
w
|
||||||
EOF
|
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:
|
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:
|
#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
|
### 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
|
line, a simple `=` (equal sign) will print this line number and thus the
|
||||||
number of lines of the file:
|
number of lines of the file:
|
||||||
|
|
||||||
@ -366,23 +366,24 @@ number of lines of the file:
|
|||||||
|
|
||||||
### cat
|
### cat
|
||||||
|
|
||||||
Yea, it's a joke\...
|
Yea, it's a joke...
|
||||||
|
|
||||||
ed -s file <<< $',p'
|
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):
|
done with the `list` command (l):
|
||||||
|
|
||||||
ed -s file <<< $',l'
|
ed -s file <<< $',l'
|
||||||
|
|
||||||
FIXME to be continued
|
!!! warning "FIXME"
|
||||||
|
to be continued
|
||||||
|
|
||||||
## Links
|
## Links
|
||||||
|
|
||||||
Reference:
|
Reference:
|
||||||
|
|
||||||
- [Gnu ed](http://www.gnu.org/software/ed/manual/ed_manual.html) - if
|
- [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
|
- POSIX
|
||||||
[ed](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ed.html#tag_20_38),
|
[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),
|
[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
|
- Being a builtin, `getopts` can set shell variables to use for
|
||||||
parsing (impossible for an *external* process!)
|
parsing (impossible for an *external* process!)
|
||||||
- There's no need to argue with several `getopt` implementations
|
- 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).
|
- `getopts` is defined in POSIX(r).
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
@ -38,7 +38,7 @@ parameters](../scripting/posparams.md).
|
|||||||
|
|
||||||
### Terminology
|
### 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:
|
Consider the following command line:
|
||||||
|
|
||||||
mybackup -x -f /etc/mybackup.conf -r ./foo.txt ./bar.txt
|
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
|
### Used variables
|
||||||
|
|
||||||
variable description
|
|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**
|
|[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.
|
|[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.
|
|[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).
|
value-combinations which arent possible in normal operation).
|
||||||
|
|
||||||
### Specify what you want
|
### Specify what you want
|
||||||
@ -114,10 +114,11 @@ The base-syntax for `getopts` is:
|
|||||||
|
|
||||||
where:
|
where:
|
||||||
|
|
||||||
`OPTSTRING` tells `getopts` which options to expect and where to expect arguments (see below)
|
|Option|Description|
|
||||||
------------- ------------------------------------------------------------------------------------
|
|------|-----------|
|
||||||
`VARNAME` tells `getopts` which shell-variable to use for option reporting
|
|`OPTSTRING`|tells `getopts` which options to expect and where to expect arguments (see below)|
|
||||||
`ARGS` tells `getopts` to parse these optional words instead of the positional parameters
|
|`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
|
#### 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),
|
If the **very first character** of the option-string is a `:` (colon),
|
||||||
which would normally be nonsense because there's no option letter
|
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
|
In productive scripts, this is usually what you want because it allows
|
||||||
you to handle errors yourself without being disturbed by annoying
|
you to handle errors yourself without being disturbed by annoying
|
||||||
messages.
|
messages.
|
||||||
@ -177,15 +178,17 @@ are indicated in an easier way.
|
|||||||
|
|
||||||
#### Verbose Mode
|
#### Verbose Mode
|
||||||
|
|
||||||
invalid option `VARNAME` is set to `?` (question-mark) and `OPTARG` is unset
|
|failure|message|
|
||||||
----------------------------- ----------------------------------------------------------------------------------------------
|
|-------|-------|
|
||||||
required argument not found `VARNAME` is set to `?` (question-mark), `OPTARG` is unset and an *error message is printed*
|
|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
|
#### Silent Mode
|
||||||
|
|
||||||
invalid option `VARNAME` is set to `?` (question-mark) and `OPTARG` is set to the (invalid) option character
|
|failure|message|
|
||||||
----------------------------- -----------------------------------------------------------------------------------------------
|
|-------|-------|
|
||||||
required argument not found `VARNAME` is set to `:` (colon) and `OPTARG` contains the option-character in question
|
|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
|
## Using it
|
||||||
|
|
||||||
@ -212,7 +215,7 @@ while getopts ":a" opt; do
|
|||||||
done
|
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.
|
below in the examples.
|
||||||
|
|
||||||
Let's do some tests:
|
Let's do some tests:
|
||||||
|
@ -23,8 +23,8 @@ The basic procedure is simple: The script checks if a specific condition
|
|||||||
doesn't start.
|
doesn't start.
|
||||||
|
|
||||||
This article describes locking with common UNIX(r) tools. There are
|
This article describes locking with common UNIX(r) tools. There are
|
||||||
other special locking tools available, But they\'re not standardized, or
|
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
|
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
|
scripts. **A tool designed for specifically for this purpose does the
|
||||||
job much better than general purpose code.**
|
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.
|
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
|
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
|
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:
|
in the filesystem that can be used as locking indicator:
|
||||||
|
|
||||||
- create files
|
- 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
|
the timestamp is similar: One step to check the timespamp, a second step
|
||||||
to set the timestamp.
|
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>
|
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
|
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*
|
suggestion* --- **sn18** 2009/12/19 08:24*
|
||||||
|
|
||||||
**Note:** While perusing the Internet, I found some people asking if the
|
**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,
|
The syscall under `mkdir` is guarenteed to work atomicly in all cases,
|
||||||
at least on Unices. Two examples of problems are NFS filesystems and
|
at least on Unices. Two examples of problems are NFS filesystems and
|
||||||
filesystems on cluster servers. With those two scenarios, dependencies
|
filesystems on cluster servers. With those two scenarios, dependencies
|
||||||
exist related to the mount options and implementation. However, I
|
exist related to the mount options and implementation. However, I
|
||||||
successfully use this simple method on an Oracle OCFS2 filesystem in a
|
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
|
4-node cluster environment. So let's just say "it should work under
|
||||||
normal conditions\".
|
normal conditions".
|
||||||
|
|
||||||
Another atomic method is setting the `noclobber` shell option
|
Another atomic method is setting the `noclobber` shell option
|
||||||
(`set -C`). That will cause redirection to fail, if the file the
|
(`set -C`). That will cause redirection to fail, if the file the
|
||||||
|
@ -35,7 +35,7 @@ anymore.
|
|||||||
### Operation modes
|
### Operation modes
|
||||||
|
|
||||||
There are four basic operation modes to *list*, *read*, *write* and
|
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:
|
command line options:
|
||||||
|
|
||||||
Mode RW-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.
|
- if you specify the `-c` option, `pax` will invert the matches, i.e.
|
||||||
it matches all filenames **except** those matching the specified
|
it matches all filenames **except** those matching the specified
|
||||||
patterns
|
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
|
files from the archive
|
||||||
- **To avoid conflicts with shell pathname expansion, it's wise to
|
- **To avoid conflicts with shell pathname expansion, it's wise to
|
||||||
quote patterns!**
|
quote patterns!**
|
||||||
@ -223,7 +223,7 @@ on the remote machine.
|
|||||||
|
|
||||||
### Backup your daily work
|
### 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.
|
POSIX.
|
||||||
|
|
||||||
Say you have write-access to a fileserver mounted on your filesystem
|
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)/
|
pax -rw -T 0000 data/ /n/mybackups/$(date +%A)/
|
||||||
|
|
||||||
This is done using the `-T` switch, which normally allows you to specify
|
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
|
a time window, but in this case, only the start time which means "today
|
||||||
at midnight\".
|
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.
|
will have a copy of the modified files.
|
||||||
|
|
||||||
[**Note:**]{.underline} The `%A` format from `date` expands to the name
|
<u>**Note:**</u> The `%A` format from `date` expands to the name
|
||||||
of the current day, localized, e.g. \"Friday\" (en) or \"Mittwoch\"
|
of the current day, localized, e.g. "Friday" (en) or "Mittwoch"
|
||||||
(de).
|
(de).
|
||||||
|
|
||||||
The same, but with an archive, can be accomplished by:
|
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
|
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
|
you want to exclude all the CVS directories to create a source code
|
||||||
archive. We are going to replace the names containing /CVS/ with
|
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.
|
entire pathname.
|
||||||
|
|
||||||
pax -w -x ustar -f release.tar -s',.*/CVS/.*,,' myapplication
|
pax -w -x ustar -f release.tar -s',.*/CVS/.*,,' myapplication
|
||||||
|
|
||||||
You can use several -s options, for instance, let's say you also want
|
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
|
pax -w -x ustar -f release.tar -'s,.*/CVS/.*,,' -'s/.*~//' myapplication
|
||||||
|
|
||||||
This can also be done while reading an archive, for instance, suppose
|
This can also be done while reading an archive, for instance, suppose
|
||||||
you have an archive containing a \"usr\" and a \"etc\" directory but
|
you have an archive containing a "usr" and a "etc" directory but
|
||||||
that you want to extract only the \"usr\" directory:
|
that you want to extract only the "usr" directory:
|
||||||
|
|
||||||
pax -r -f archive.tar -s',^etc/.*,,' #the etc/ dir is not extracted
|
pax -r -f archive.tar -s',^etc/.*,,' #the etc/ dir is not extracted
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ tags:
|
|||||||
# Illustrated Redirection Tutorial
|
# Illustrated Redirection Tutorial
|
||||||
|
|
||||||
This tutorial is not a complete guide to redirection, it will not cover
|
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.
|
to understand what things like `3>&2`, `2>&1` or `1>&3-` do.
|
||||||
|
|
||||||
# stdin, stdout, stderr
|
# 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`)
|
`2` also known as standard input (`stdin`), standard output (`stdout`)
|
||||||
and standard error (`stderr`).
|
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:
|
see:
|
||||||
|
|
||||||
# lsof +f g -ap $BASHPID -d 0,1,2
|
# lsof +f g -ap $BASHPID -d 0,1,2
|
||||||
@ -54,7 +54,7 @@ connected to `/dev/pts/5`.
|
|||||||
|
|
||||||
# Simple Redirections
|
# Simple Redirections
|
||||||
|
|
||||||
## Output Redirection \"n> file\"
|
## Output Redirection "n> file"
|
||||||
|
|
||||||
`>` is probably the simplest redirection.
|
`>` 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
|
What will the command do with this descriptor? It depends. Often
|
||||||
nothing. We will see later why we might want other file descriptors.
|
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
|
When you run a commandusing `command < file`, it changes the file
|
||||||
descriptor `0` so that it looks like:
|
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,
|
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.
|
`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
|
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
|
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
|
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
|
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
|
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
|
`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
|
was. This is often misunderstood by people wanting to redirect both
|
||||||
standard input and standard output to the file. Continue reading for
|
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
|
`s` will append a line to a file as will writing a line to file
|
||||||
descriptor `t`.
|
descriptor `t`.
|
||||||
|
|
||||||
<note tip>The syntax is somewhat confusing in that you would think
|
!!! info "Tip"
|
||||||
that the arrow would point in the direction of the copy, but it's
|
The syntax is somewhat confusing in that you would think
|
||||||
reversed. So it's `target>&source` effectively.</note>
|
that the arrow would point in the direction of the copy, but it's
|
||||||
|
reversed. So it's `target>&source` effectively.
|
||||||
|
|
||||||
So, as a simple example (albeit slightly contrived), is the following:
|
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
|
exec 1>&3 # Copy 3 back into 1
|
||||||
echo Done # Output to original stdout
|
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
|
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.
|
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.
|
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
|
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
|
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.
|
actually executed.
|
||||||
|
|
||||||
So **BEFORE** sed starts, standard output has already been redirected,
|
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.
|
truncated. When `sed` starts to read the file, it contains nothing.
|
||||||
|
|
||||||
## exec
|
## exec
|
||||||
@ -447,8 +448,8 @@ it. It's probably better to do something like:
|
|||||||
|
|
||||||
#we don't need 3 any more
|
#we don't need 3 any more
|
||||||
|
|
||||||
I\'ve seen some people using this as a way to discard, say stderr, using
|
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
|
something like: command 2>&-. Though it might work, I'm not sure if
|
||||||
you can expect all applications to behave correctly with a closed
|
you can expect all applications to behave correctly with a closed
|
||||||
stderr.
|
stderr.
|
||||||
|
|
||||||
@ -598,11 +599,11 @@ original `stderr`.
|
|||||||
# Syntax
|
# Syntax
|
||||||
|
|
||||||
I used to have trouble choosing between `0&<3` `3&>1` `3>&1` `->2`
|
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
|
more representative of the result, i.e., the redirection, than what is
|
||||||
done, i.e., opening, closing, or duplicating file descriptors).
|
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:
|
help you, a redirection is always like the following:
|
||||||
|
|
||||||
lhs op rhs
|
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 `>>`,
|
the op is `<` then there is an implicit 0, if it's `>` or `>>`,
|
||||||
there is an implicit 1.
|
there is an implicit 1.
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
- `op` is `<`, `>`, `>>`, `>|`, or `<>`:
|
- `op` is `<`, `>`, `>>`, `>|`, or `<>`:
|
||||||
- `<` if the file decriptor in `lhs` will be read, `>` if it will
|
- `<` if the file decriptor in `lhs` will be read, `>` if it will
|
||||||
be written, `>>` if data is to be appended to the file, `>|` to
|
be written, `>>` if data is to be appended to the file, `>|` to
|
||||||
overwrite an existing file or `<>` if it will be both read and
|
overwrite an existing file or `<>` if it will be both read and
|
||||||
written.
|
written.
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
- `rhs` is the thing that the file descriptor will describe:
|
- `rhs` is the thing that the file descriptor will describe:
|
||||||
- It can be the name of a file, the place where another descriptor
|
- It can be the name of a file, the place where another descriptor
|
||||||
goes (`&1`), or, `&-`, which will close the file descriptor.
|
goes (`&1`), or, `&-`, which will close the file descriptor.
|
||||||
@ -638,49 +633,34 @@ The shell is pretty loose about what it considers a valid redirect.
|
|||||||
While opinions probably differ, this author has some (strong)
|
While opinions probably differ, this author has some (strong)
|
||||||
recommendations:
|
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
|
not** include whitespace anywhere within the redirection syntax
|
||||||
except within quotes if required on the RHS (e.g. a filename that
|
except within quotes if required on the RHS (e.g. a filename that
|
||||||
contains a space). Since shells fundamentally use whitespace to
|
contains a space). Since shells fundamentally use whitespace to
|
||||||
delimit fields in general, it is visually much clearer for each
|
delimit fields in general, it is visually much clearer for each
|
||||||
redirection to be separated by whitespace, but grouped in chunks
|
redirection to be separated by whitespace, but grouped in chunks
|
||||||
that contain no unnecessary whitespace.
|
that contain no unnecessary whitespace.
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
- **Do** always put a space between each redirection, and between the
|
- **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
|
- **Always** place redirections together at the very end of a command
|
||||||
after all arguments. Never precede a command with a redirect. Never
|
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
|
- **Never** use the Csh `&>foo` and `>&foo` shorthand redirects. Use
|
||||||
the long form `>foo 2>&1`. (see: [obsolete](../scripting/obsolete.md))
|
the long form `>foo 2>&1`. (see: [obsolete](../scripting/obsolete.md))
|
||||||
|
|
||||||
```{=html}
|
```bash
|
||||||
<!-- -->
|
# Good! This is clearly a simple commmand with two arguments and 4 redirections
|
||||||
|
cmd arg1 arg2 <myFile 3<&1 2>/dev/null >&2
|
||||||
|
|
||||||
|
# Good!
|
||||||
|
{ cmd1 <<<'my input'; cmd2; } >someFile
|
||||||
|
|
||||||
|
# Bad. Is the "1" a file descriptor or an argument to cmd? (answer: it's the FD). Is the space after the herestring part of the input data? (answer: No).
|
||||||
|
# The redirects are also not delimited in any obvious way.
|
||||||
|
cmd 2>& 1 <<< stuff
|
||||||
|
|
||||||
|
# Hideously Bad. It's difficult to tell where the redirects are and whether they're even valid redirects.
|
||||||
|
# This is in fact one command with one argument, an assignment, and three redirects.
|
||||||
|
foo=bar<baz bork<<< blarg>bleh
|
||||||
```
|
```
|
||||||
# Good! This is clearly a simple commmand with two arguments and 4 redirections
|
|
||||||
cmd arg1 arg2 <myFile 3<&1 2>/dev/null >&2
|
|
||||||
|
|
||||||
# Good!
|
|
||||||
{ cmd1 <<<'my input'; cmd2; } >someFile
|
|
||||||
|
|
||||||
# Bad. Is the "1" a file descriptor or an argument to cmd? (answer: it's the FD). Is the space after the herestring part of the input data? (answer: No).
|
|
||||||
# The redirects are also not delimited in any obvious way.
|
|
||||||
cmd 2>& 1 <<< stuff
|
|
||||||
|
|
||||||
# Hideously Bad. It's difficult to tell where the redirects are and whether they're even valid redirects.
|
|
||||||
# This is in fact one command with one argument, an assignment, and three redirects.
|
|
||||||
foo=bar<baz bork<<< blarg>bleh
|
|
||||||
|
|
||||||
# Conclusion
|
# Conclusion
|
||||||
|
|
||||||
@ -689,9 +669,9 @@ I hope this tutorial worked for you.
|
|||||||
I lied, I did not explain `1>&3-`, go check the manual ;-)
|
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
|
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:
|
there too:
|
||||||
|
|
||||||
- [A Detailed Introduction to I/O and I/O
|
- [A Detailed Introduction to I/O and I/O
|
||||||
|
@ -23,7 +23,7 @@ We have a simple **stat.sh** script:
|
|||||||
echo "PYTHON LINES: $LINES"
|
echo "PYTHON LINES: $LINES"
|
||||||
|
|
||||||
This script evaluate the number of python files and the number of python
|
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
|
### Create testsuit
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ tags:
|
|||||||
|
|
||||||
# List of shell options
|
# 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.
|
then new options are added, so likely, this list isn't complete.
|
||||||
|
|
||||||
The shell-options can be set with the [shopt builtin
|
The shell-options can be set with the [shopt builtin
|
||||||
@ -21,35 +21,35 @@ command](../commands/builtin/shopt.md).
|
|||||||
|
|
||||||
### autocd
|
### autocd
|
||||||
|
|
||||||
Option: `autocd` Since: 4.0-alpha
|
| Option: | `autocd` | Since: | 4.0-alpha |
|
||||||
------------- ------------------ ---------- -----------
|
|:------------|:-----------------|:---------|:----------|
|
||||||
Shell mode: interactive only Default: off
|
| Shell mode: | interactive only | Default: | off |
|
||||||
|
|
||||||
If set, a command name that is the name of a directory is executed as if
|
If set, a command name that is the name of a directory is executed as if
|
||||||
it were the argument to the cd command.
|
it were the argument to the cd command.
|
||||||
|
|
||||||
### assoc_expand_once
|
### assoc_expand_once
|
||||||
|
|
||||||
Option: `assoc_expand_once` Since: 5.0-alpha
|
| Option: | `assoc_expand_once` | Since: | 5.0-alpha |
|
||||||
------------- --------------------- ---------- -----------
|
|:------------|:--------------------|:---------|:----------|
|
||||||
Shell mode: all Default: off
|
| Shell mode: | all | Default: | off |
|
||||||
|
|
||||||
If set, Bash attempts to expand associative array options only once.
|
If set, Bash attempts to expand associative array options only once.
|
||||||
|
|
||||||
### cdable_vars
|
### cdable_vars
|
||||||
|
|
||||||
Option: `cdable_vars` Since: unknown
|
| Option: | `cdable_vars` | Since: | unknown |
|
||||||
------------- --------------- ---------- ---------
|
|:------------|:--------------|:---------|:--------|
|
||||||
Shell mode: all Default: off
|
| Shell mode: | all | Default: | off |
|
||||||
|
|
||||||
Treat every **non-directory argument** to the `cd`-command as variable
|
Treat every **non-directory argument** to the `cd`-command as variable
|
||||||
name containing a directory to `cd` into.
|
name containing a directory to `cd` into.
|
||||||
|
|
||||||
### cdspell
|
### cdspell
|
||||||
|
|
||||||
Option: `cdspell` Since: unknown
|
| Option: | `cdspell` | Since: | unknown |
|
||||||
------------- ------------------ ---------- ---------
|
|:------------|:-----------------|:---------|:--------|
|
||||||
Shell mode: interactive only Default: off
|
| Shell mode: | interactive only | Default: | off |
|
||||||
|
|
||||||
If set, minor errors in the spelling of a directory component in a cd
|
If set, minor errors in the spelling of a directory component in a cd
|
||||||
command will be corrected. The errors checked for are transposed
|
command will be corrected. The errors checked for are transposed
|
||||||
@ -59,9 +59,9 @@ proceeds.
|
|||||||
|
|
||||||
### checkhash
|
### checkhash
|
||||||
|
|
||||||
Option: `checkhash` Since: unknown
|
| Option: | `checkhash` | Since: | unknown |
|
||||||
------------- ------------- ---------- ---------
|
|:------------|:------------|:---------|:--------|
|
||||||
Shell mode: all Default: off
|
| Shell mode: | all | Default: | off |
|
||||||
|
|
||||||
If set, Bash checks that a command found in the hash table exists before
|
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
|
trying to execute it. If a hashed command no longer exists, a normal
|
||||||
@ -69,9 +69,9 @@ path search is performed.
|
|||||||
|
|
||||||
### checkjobs
|
### checkjobs
|
||||||
|
|
||||||
Option: `checkjobs` Since: 4.0-alpha
|
| Option: | `checkjobs` | Since: | 4.0-alpha |
|
||||||
------------- ------------------ ---------- -----------
|
|:------------|:-----------------|:---------|:----------|
|
||||||
Shell mode: interactive only Default: off
|
| Shell mode: | interactive only | Default: | off |
|
||||||
|
|
||||||
If set, Bash lists the status of any stopped and running jobs before
|
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
|
exiting an interactive shell. If any jobs are running, this causes the
|
||||||
@ -81,9 +81,9 @@ stopped.
|
|||||||
|
|
||||||
### checkwinsize
|
### checkwinsize
|
||||||
|
|
||||||
Option: `checkwinsize` Since: unknown
|
| Option: | `checkwinsize` | Since: | unknown |
|
||||||
------------- ---------------- ---------- ---------
|
|:------------|:---------------|:---------|:--------|
|
||||||
Shell mode: all Default: on
|
| Shell mode: | all | Default: | on |
|
||||||
|
|
||||||
If set, Bash checks the window size after each command and, if
|
If set, Bash checks the window size after each command and, if
|
||||||
necessary, updates the values of the variables
|
necessary, updates the values of the variables
|
||||||
@ -92,9 +92,9 @@ necessary, updates the values of the variables
|
|||||||
|
|
||||||
### cmdhist
|
### cmdhist
|
||||||
|
|
||||||
Option: `cmdhist` Since: unknown
|
| Option: | `cmdhist` | Since: | unknown |
|
||||||
------------- ----------- ---------- ---------
|
|:------------|:----------|:---------|:--------|
|
||||||
Shell mode: all Default: off
|
| Shell mode: | all | Default: | off |
|
||||||
|
|
||||||
If set, Bash attempts to save all lines of a multiple-line command in
|
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
|
the same history entry. This allows easy re-editing of multi-line
|
||||||
@ -102,65 +102,64 @@ commands.
|
|||||||
|
|
||||||
### compat31
|
### compat31
|
||||||
|
|
||||||
Option: `compat31` Since: 3.2
|
| Option: | `compat31` | Since: | 3.2 |
|
||||||
------------- ------------ ---------- -----
|
|:------------|:-----------|:---------|:----|
|
||||||
Shell mode: all Default: off
|
| Shell mode: | all | Default: | off |
|
||||||
|
|
||||||
Compatiblity mode for Bash 3.1
|
Compatiblity mode for Bash 3.1
|
||||||
|
|
||||||
### compat32
|
### compat32
|
||||||
|
|
||||||
Option: `compat32` Since: 4.0
|
| Option: | `compat32` | Since: | 4.0 |
|
||||||
------------- ------------ ---------- -----
|
|:------------|:-----------|:---------|:----|
|
||||||
Shell mode: all Default: off
|
| Shell mode: | all | Default: | off |
|
||||||
|
|
||||||
Compatiblity mode for Bash 3.2
|
Compatiblity mode for Bash 3.2
|
||||||
|
|
||||||
### compat40
|
### compat40
|
||||||
|
|
||||||
Option: `compat40` Since: 4.1-beta
|
| Option: | `compat40` | Since: | 4.1-beta |
|
||||||
------------- ------------ ---------- ----------
|
|:------------|:-----------|:---------|:---------|
|
||||||
Shell mode: all Default: off
|
| Shell mode: | all | Default: | off |
|
||||||
|
|
||||||
Compatiblity mode for Bash 4.0
|
Compatiblity mode for Bash 4.0
|
||||||
|
|
||||||
### compat41
|
### compat41
|
||||||
|
|
||||||
Option: `compat41` Since: 4.2-alpha
|
| Option: | `compat41` | Since: | 4.2-alpha |
|
||||||
------------- ------------ ---------- -----------
|
|:------------|:-----------|:---------|:----------|
|
||||||
Shell mode: all Default: off
|
| Shell mode: | all | Default: | off |
|
||||||
|
|
||||||
Compatiblity mode for Bash 4.1
|
Compatiblity mode for Bash 4.1
|
||||||
|
|
||||||
### compat42
|
### compat42
|
||||||
|
|
||||||
Option: `compat42` Since: 4.3-alpha
|
| Option: | `compat42` | Since: | 4.3-alpha |
|
||||||
------------- ------------ ---------- -----------
|
|:------------|:-----------|:---------|:----------|
|
||||||
Shell mode: all Default: off
|
| Shell mode: | all | Default: | off |
|
||||||
|
|
||||||
Compatiblity mode for Bash 4.2
|
Compatiblity mode for Bash 4.2
|
||||||
|
|
||||||
### compat43
|
### compat43
|
||||||
|
|
||||||
Option: `compat43` Since: 4.4-alpha
|
| Option: | `compat43` | Since: | 4.4-alpha |
|
||||||
------------- ------------ ---------- -----------
|
|:------------|:-----------|:---------|:----------|
|
||||||
Shell mode: all Default: off
|
| Shell mode: | all | Default: | off |
|
||||||
|
|
||||||
Compatiblity mode for Bash 4.3
|
Compatiblity mode for Bash 4.3
|
||||||
|
|
||||||
### compat44
|
### compat44
|
||||||
|
|
||||||
Option: `compat44` Since: 5.0-alpha
|
| Option: | `compat44` | Since: | 5.0-alpha |
|
||||||
------------- ------------ ---------- -----------
|
|:------------|:-----------|:---------|:----------|
|
||||||
Shell mode: all Default: off
|
| Shell mode: | all | Default: | off |
|
||||||
|
|
||||||
Compatiblity mode for Bash 4.4
|
Compatiblity mode for Bash 4.4
|
||||||
|
|
||||||
### direxpand
|
### direxpand
|
||||||
|
|
||||||
Option: `direxpand` Since: 4.3-alpha
|
| Option: | `direxpand` | Since: | 4.3-alpha |
|
||||||
------------- ------------- ---------- ------------------------------------------------------------------------
|
|:------------|:------------|:---------|:-----------------------------------------------------------------------|
|
||||||
Shell mode: all Default: off (unless changed on compile-time with `--enable-direxpand-default`)
|
| 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
|
If set, bash replaces directory names with the results of word expansion
|
||||||
when performing filename completion. This changes the contents of the
|
when performing filename completion. This changes the contents of the
|
||||||
@ -169,27 +168,27 @@ user typed.
|
|||||||
|
|
||||||
### dirspell
|
### dirspell
|
||||||
|
|
||||||
Option: `dirspell` Since: 4.0-alpha
|
| Option: | `dirspell` | Since: | 4.0-alpha |
|
||||||
------------- ------------ ---------- -----------
|
|:------------|:-----------|:---------|:----------|
|
||||||
Shell mode: all Default: off
|
| Shell mode: | all | Default: | off |
|
||||||
|
|
||||||
If set, Bash will perform spelling corrections on directory names to
|
If set, Bash will perform spelling corrections on directory names to
|
||||||
match a glob.
|
match a glob.
|
||||||
|
|
||||||
### dotglob
|
### dotglob
|
||||||
|
|
||||||
Option: `dotglob` Since: unknown
|
| Option: | `dotglob` | Since: | unknown |
|
||||||
------------- ----------- ---------- ---------
|
|:------------|:----------|:---------|:--------|
|
||||||
Shell mode: all Default: off
|
| Shell mode: | all | Default: | off |
|
||||||
|
|
||||||
If set, Bash includes filenames beginning with a `.` (dot) in the
|
If set, Bash includes filenames beginning with a `.` (dot) in the
|
||||||
results of [pathname expansion](../syntax/expansion/globs.md).
|
results of [pathname expansion](../syntax/expansion/globs.md).
|
||||||
|
|
||||||
### execfail
|
### execfail
|
||||||
|
|
||||||
Option: `execfail` Since: unknown
|
| Option: | `execfail` | Since: | unknown |
|
||||||
------------- ----------------- ---------- ---------
|
|:------------|:----------------|:---------|:--------|
|
||||||
Shell mode: non-interactive Default: off
|
| Shell mode: | non-interactive | Default: | off |
|
||||||
|
|
||||||
If set, a non-interactive shell will not exit if it cannot execute the
|
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
|
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
|
### expand_aliases
|
||||||
|
|
||||||
Option: `expand_aliases` Since: unknown
|
| Option: | `expand_aliases` | Since: | unknown |
|
||||||
------------- ------------------ ---------- -----------------------------------------
|
|:------------|:-----------------|:---------|:----------------------------------------|
|
||||||
Shell mode: all Default: on (interactive), off (non-interactive)
|
| Shell mode: | all | Default: | on (interactive), off (non-interactive) |
|
||||||
|
|
||||||
If set, aliases are expanded. This option is enabled by default for
|
If set, aliases are expanded. This option is enabled by default for
|
||||||
interactive shells.
|
interactive shells.
|
||||||
|
|
||||||
### extdebug
|
### extdebug
|
||||||
|
|
||||||
Option: `extdebug` Since: 3.0-alpha
|
| Option: | `extdebug` | Since: | 3.0-alpha |
|
||||||
------------- ------------ ---------- -----------
|
|:------------|:-----------|:---------|:----------|
|
||||||
Shell mode: all Default: off
|
| Shell mode: | all | Default: | off |
|
||||||
|
|
||||||
If set, behavior intended for use by debuggers is enabled.
|
If set, behavior intended for use by debuggers is enabled.
|
||||||
|
|
||||||
### extglob
|
### extglob
|
||||||
|
|
||||||
Option: `extglob` Since: 2.02-alpha1
|
| Option: | `extglob` | Since: | 2.02-alpha1 |
|
||||||
------------- ----------- ---------- -------------
|
|:------------|:----------|:---------|:------------|
|
||||||
Shell mode: all Default: off
|
| Shell mode: | all | Default: | off |
|
||||||
|
|
||||||
If set, the extended [pattern matching](../syntax/pattern.md) features are
|
If set, the extended [pattern matching](../syntax/pattern.md) features are
|
||||||
enabled. See the important note below under [Parser
|
enabled. See the important note below under [Parser
|
||||||
@ -224,9 +223,9 @@ configurations](#parser_configurations).
|
|||||||
|
|
||||||
### extquote
|
### extquote
|
||||||
|
|
||||||
Option: `extquote` Since: 3.0-alpha (?)
|
| Option: | `extquote` | Since: | 3.0-alpha (?) |
|
||||||
------------- ------------ ---------- ---------------
|
|:------------|:-----------|:---------|:--------------|
|
||||||
Shell mode: all Default: on
|
| Shell mode: | all | Default: | on |
|
||||||
|
|
||||||
If set, `$'string'` and `$"string"` quoting is performed within
|
If set, `$'string'` and `$"string"` quoting is performed within
|
||||||
[parameter expansions](../syntax/pe.md) enclosed in double quotes. See the
|
[parameter expansions](../syntax/pe.md) enclosed in double quotes. See the
|
||||||
@ -235,18 +234,18 @@ configurations](#parser_configurations).
|
|||||||
|
|
||||||
### failglob
|
### failglob
|
||||||
|
|
||||||
Option: `failglob` Since: 3.0-alpha
|
| Option: | `failglob` | Since: | 3.0-alpha |
|
||||||
------------- ------------ ---------- -----------
|
|:------------|:-----------|:---------|:----------|
|
||||||
Shell mode: all Default: off
|
| Shell mode: | all | Default: | off |
|
||||||
|
|
||||||
If set, patterns which fail to match filenames during pathname expansion
|
If set, patterns which fail to match filenames during pathname expansion
|
||||||
result in an error message.
|
result in an error message.
|
||||||
|
|
||||||
### force_fignore
|
### force_fignore
|
||||||
|
|
||||||
Option: `force_fignore` Since: 3.0-alpha
|
| Option: | `force_fignore` | Since: | 3.0-alpha |
|
||||||
------------- ----------------- ---------- -----------
|
|:------------|:----------------|:---------|:----------|
|
||||||
Shell mode: interactive Default: on
|
| Shell mode: | interactive | Default: | on |
|
||||||
|
|
||||||
If set, the suffixes specified by the
|
If set, the suffixes specified by the
|
||||||
[FIGNORE](../syntax/shellvars.md#FIGNORE) shell variable cause words to be
|
[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
|
### globasciiranges
|
||||||
|
|
||||||
Option: `globasciiranges` Since: 4.3-alpha
|
| Option: | `globasciiranges` | Since: | 4.3-alpha |
|
||||||
------------- ------------------- ---------- -----------------------------------
|
|:------------|:------------------|:---------|:----------------------------------|
|
||||||
Shell mode: all Default: on (configurable at compile time)
|
| Shell mode: | all | Default: | on (configurable at compile time) |
|
||||||
|
|
||||||
If set, range expressions used in pattern matching behave as if in the
|
If set, range expressions used in pattern matching behave as if in the
|
||||||
traditional C locale when performing comparisons. That is, the current
|
traditional C locale when performing comparisons. That is, the current
|
||||||
@ -267,26 +266,26 @@ will collate together.
|
|||||||
|
|
||||||
### globstar
|
### globstar
|
||||||
|
|
||||||
Option: `globstar` Since: 4.0-alpha
|
| Option: | `globstar` | Since: | 4.0-alpha |
|
||||||
------------- ------------ ---------- -----------
|
|:------------|:-----------|:---------|:----------|
|
||||||
Shell mode: all Default: off
|
| Shell mode: | all | Default: | off |
|
||||||
|
|
||||||
If set, recursive globbing with `**` is enabled.
|
If set, recursive globbing with `**` is enabled.
|
||||||
|
|
||||||
### gnu_errfmt
|
### gnu_errfmt
|
||||||
|
|
||||||
Option: `gnu_errfmt` Since: 3.0-alpha
|
| Option: | `gnu_errfmt` | Since: | 3.0-alpha |
|
||||||
------------- -------------- ---------- -----------
|
|:------------|:-------------|:---------|:----------|
|
||||||
Shell mode: all Default: off
|
| Shell mode: | all | Default: | off |
|
||||||
|
|
||||||
If set, shell error messages are written in the \"standard GNU error
|
If set, shell error messages are written in the "standard GNU error
|
||||||
message format\".
|
message format".
|
||||||
|
|
||||||
### histappend
|
### histappend
|
||||||
|
|
||||||
Option: `histappend` Since: unknown
|
| Option: | `histappend` | Since: | unknown |
|
||||||
------------- ----------------- ---------- ---------
|
|:------------|:----------------|:---------|:--------|
|
||||||
Shell mode: interactive (?) Default: off
|
| Shell mode: | interactive (?) | Default: | off |
|
||||||
|
|
||||||
If set, the history list is appended to the file named by the value of
|
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
|
the [HISTFILE](../syntax/shellvars.md#HISTFILE) variable when the shell
|
||||||
@ -294,53 +293,53 @@ exits, rather than overwriting the file.
|
|||||||
|
|
||||||
### histreedit
|
### histreedit
|
||||||
|
|
||||||
Option: `histreedit` Since: unknown
|
| Option: | `histreedit` | Since: | unknown |
|
||||||
------------- ----------------- ---------- ---------
|
|:------------|:----------------|:---------|:--------|
|
||||||
Shell mode: interactive (?) Default: off
|
| Shell mode: | interactive (?) | Default: | off |
|
||||||
|
|
||||||
If set, and readline is being used, a user is given the opportunity to
|
If set, and readline is being used, a user is given the opportunity to
|
||||||
re-edit a failed history substitution.
|
re-edit a failed history substitution.
|
||||||
|
|
||||||
### histverify
|
### histverify
|
||||||
|
|
||||||
Option: `histverify` Since: unknown
|
| Option: | `histverify` | Since: | unknown |
|
||||||
------------- ----------------- ---------- ---------
|
|:------------|:----------------|:---------|:--------|
|
||||||
Shell mode: interactive (?) Default: off
|
| Shell mode: | interactive (?) | Default: | off |
|
||||||
|
|
||||||
Allow to review a history substitution result by loading the resulting
|
Allow to review a history substitution result by loading the resulting
|
||||||
line into the editing buffer, rather than directly executing it.
|
line into the editing buffer, rather than directly executing it.
|
||||||
|
|
||||||
### hostcomplete
|
### hostcomplete
|
||||||
|
|
||||||
Option: `hostcomplete` Since: 2.0-alpha3
|
| Option: | `hostcomplete` | Since: | 2.0-alpha3 |
|
||||||
------------- ----------------- ---------- ------------
|
|:------------|:----------------|:---------|:-----------|
|
||||||
Shell mode: interactive (?) Default: on
|
| Shell mode: | interactive (?) | Default: | on |
|
||||||
|
|
||||||
If set, Bash completion also completes hostnames. On by default.
|
If set, Bash completion also completes hostnames. On by default.
|
||||||
|
|
||||||
### huponexit
|
### huponexit
|
||||||
|
|
||||||
Option: `huponexit` Since: 2.02-alpha1
|
| Option: | `huponexit` | Since: | 2.02-alpha1 |
|
||||||
------------- ------------------- ---------- -------------
|
|:------------|:------------------|:---------|:------------|
|
||||||
Shell mode: interactive login Default: off
|
| Shell mode: | interactive login | Default: | off |
|
||||||
|
|
||||||
If set, Bash will send the `SIGHUP` signal to all jobs when an
|
If set, Bash will send the `SIGHUP` signal to all jobs when an
|
||||||
interactive login shell exits.
|
interactive login shell exits.
|
||||||
|
|
||||||
### interactive_comments
|
### interactive_comments
|
||||||
|
|
||||||
Option: `interactive_comments` Since: unknown
|
| Option: | `interactive_comments` | Since: | unknown |
|
||||||
------------- ------------------------ ---------- ---------
|
|:------------|:-----------------------|:---------|:--------|
|
||||||
Shell mode: interactive Default: on
|
| Shell mode: | interactive | Default: | on |
|
||||||
|
|
||||||
Allow [commenting](../scripting/basics.md#comments) in interactive shells, on
|
Allow [commenting](../scripting/basics.md#comments) in interactive shells, on
|
||||||
by default.
|
by default.
|
||||||
|
|
||||||
### lastpipe
|
### lastpipe
|
||||||
|
|
||||||
Option: `lastpipe` Since: 4.2-alpha
|
| Option: | `lastpipe` | Since: | 4.2-alpha |
|
||||||
------------- ------------ ---------- -----------
|
|:------------|:-----------|:---------|:----------|
|
||||||
Shell mode: all Default: off
|
| Shell mode: | all | Default: | off |
|
||||||
|
|
||||||
If set, **and job control is not active**, the shell runs the last
|
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
|
command of a pipeline not executed in the background in the current
|
||||||
@ -348,9 +347,9 @@ shell environment.
|
|||||||
|
|
||||||
### lithist
|
### lithist
|
||||||
|
|
||||||
Option: `lithist` Since: unknown
|
| Option: | `lithist` | Since: | unknown |
|
||||||
------------- ------------- ---------- ---------
|
|:------------|:------------|:---------|:--------|
|
||||||
Shell mode: interactive Default: off
|
| Shell mode: | interactive | Default: | off |
|
||||||
|
|
||||||
If set, and the [#cmdhist](#cmdhist) option is enabled, multi-line
|
If set, and the [#cmdhist](#cmdhist) option is enabled, multi-line
|
||||||
commands are saved to the history with embedded newlines rather than
|
commands are saved to the history with embedded newlines rather than
|
||||||
@ -358,36 +357,36 @@ using semicolon separators where possible.
|
|||||||
|
|
||||||
### localvar_inherit
|
### localvar_inherit
|
||||||
|
|
||||||
Option: `localvar_inherit` Since: 5.0-alpha
|
| Option: | `localvar_inherit` | Since: | 5.0-alpha |
|
||||||
------------- -------------------- ---------- -----------
|
|:------------|:-------------------|:---------|:----------|
|
||||||
Shell mode: all Default: off
|
| Shell mode: | all | Default: | off |
|
||||||
|
|
||||||
If this option is set, a local variable inherits the value of a variable
|
If this option is set, a local variable inherits the value of a variable
|
||||||
with the same name at the nearest preceding scope.
|
with the same name at the nearest preceding scope.
|
||||||
|
|
||||||
### login_shell
|
### login_shell
|
||||||
|
|
||||||
Option: `login_shell` Since: 2.05a-alpha1
|
| Option: | `login_shell` | Since: | 2.05a-alpha1 |
|
||||||
------------- --------------- ---------- --------------
|
|:------------|:--------------|:---------|:-------------|
|
||||||
Shell mode: all Default: n/a
|
| Shell mode: | all | Default: | n/a |
|
||||||
|
|
||||||
The option is set when Bash is a login shell. This is a readonly option.
|
The option is set when Bash is a login shell. This is a readonly option.
|
||||||
|
|
||||||
### mailwarn
|
### mailwarn
|
||||||
|
|
||||||
Option: `mailwarn` Since: unknown
|
| Option: | `mailwarn` | Since: | unknown |
|
||||||
------------- ----------------- ---------- ---------
|
|:------------|:----------------|:---------|:--------|
|
||||||
Shell mode: interactive (?) Default: off
|
| Shell mode: | interactive (?) | Default: | off |
|
||||||
|
|
||||||
If set, and a file that Bash is checking for mail has been accessed
|
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
|
since the last time it was checked, the message "The mail in mailfile
|
||||||
has been read\" is displayed.
|
has been read" is displayed.
|
||||||
|
|
||||||
### no_empty_cmd_completion
|
### no_empty_cmd_completion
|
||||||
|
|
||||||
Option: `mailwarn` Since: unknown
|
| Option: | `mailwarn` | Since: | unknown |
|
||||||
------------- ----------------- ---------- ---------
|
|:------------|:----------------|:---------|:--------|
|
||||||
Shell mode: interactive (?) Default: off
|
| Shell mode: | interactive (?) | Default: | off |
|
||||||
|
|
||||||
If set, and readline is being used, Bash will not attempt to search the
|
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
|
PATH for possible completions when completion is attempted on an empty
|
||||||
@ -395,45 +394,45 @@ line.
|
|||||||
|
|
||||||
### nocaseglob
|
### nocaseglob
|
||||||
|
|
||||||
Option: `nocaseglob` Since: 2.02-alpha1
|
| Option: | `nocaseglob` | Since: | 2.02-alpha1 |
|
||||||
------------- -------------- ---------- -------------
|
|:------------|:-------------|:---------|:------------|
|
||||||
Shell mode: all Default: off
|
| Shell mode: | all | Default: | off |
|
||||||
|
|
||||||
If set, Bash matches filenames in a case-insensitive fashion when
|
If set, Bash matches filenames in a case-insensitive fashion when
|
||||||
performing pathname expansion.
|
performing pathname expansion.
|
||||||
|
|
||||||
### nocasematch
|
### nocasematch
|
||||||
|
|
||||||
Option: `nocasematch` Since: 3.1-alpha1
|
| Option: | `nocasematch` | Since: | 3.1-alpha1 |
|
||||||
------------- --------------- ---------- ------------
|
|:------------|:--------------|:---------|:-----------|
|
||||||
Shell mode: all Default: off
|
| Shell mode: | all | Default: | off |
|
||||||
|
|
||||||
If set, Bash matches patterns in a case-insensitive fashion when
|
If set, Bash matches patterns in a case-insensitive fashion when
|
||||||
performing matching while executing `case` or `[[` conditional commands.
|
performing matching while executing `case` or `[[` conditional commands.
|
||||||
|
|
||||||
### nullglob
|
### nullglob
|
||||||
|
|
||||||
Option: `nullglob` Since: unknown
|
| Option: | `nullglob` | Since: | unknown |
|
||||||
------------- ------------ ---------- ---------
|
|:------------|:-----------|:---------|:--------|
|
||||||
Shell mode: all Default: off
|
| Shell mode: | all | Default: | off |
|
||||||
|
|
||||||
If set, Bash allows patterns which match no files to expand to a null
|
If set, Bash allows patterns which match no files to expand to a null
|
||||||
string, rather than themselves.
|
string, rather than themselves.
|
||||||
|
|
||||||
### progcomp
|
### progcomp
|
||||||
|
|
||||||
Option: `progcomp` Since: 2.04-alpha1
|
|Option:|`progcomp`|Since:|2.04-alpha1|
|
||||||
------------- ----------------- ---------- -------------
|
|-------|----------|------|----------|
|
||||||
Shell mode: interactive (?) Default: on
|
|Shell mode:|interactive (?)|Default:|on|
|
||||||
|
|
||||||
If set, the programmable completion facilities are enabled. This option
|
If set, the programmable completion facilities are enabled. This option
|
||||||
is enabled by default.
|
is enabled by default.
|
||||||
|
|
||||||
### promptvars
|
### promptvars
|
||||||
|
|
||||||
Option: `promptvars` Since: unknown
|
|Option:|`promptvars`|Since:|unknown|
|
||||||
------------- -------------- ---------- ---------
|
|-------|------------|------|-------|
|
||||||
Shell mode: interactive Default: on
|
|Shell mode:|interactive|Default:|on|
|
||||||
|
|
||||||
If set, prompt strings undergo parameter expansion, command
|
If set, prompt strings undergo parameter expansion, command
|
||||||
substitution, arithmetic expansion, and quote removal after being
|
substitution, arithmetic expansion, and quote removal after being
|
||||||
@ -442,27 +441,27 @@ default.
|
|||||||
|
|
||||||
### restricted_shell
|
### restricted_shell
|
||||||
|
|
||||||
Option: `restricted_shell` Since: 2.03-alpha
|
|Option:|`restricted_shell`|Since:|2.03-alpha|
|
||||||
------------- -------------------- ---------- ------------
|
|-------|------------------|------|-------|
|
||||||
Shell mode: interactive (?) Default: off
|
|Shell mode:|interactive (?)|Default:|off|
|
||||||
|
|
||||||
The option is set when Bash is a restricted shell. This is a readonly
|
The option is set when Bash is a restricted shell. This is a readonly
|
||||||
option.
|
option.
|
||||||
|
|
||||||
### shift_verbose
|
### shift_verbose
|
||||||
|
|
||||||
Option: `shift_verbose` Since: unknown
|
|Option:|`shift_verbose`|Since:|unknown|
|
||||||
------------- ----------------- ---------- -----------------------
|
|-------|---------------|------|-------|
|
||||||
Shell mode: all Default: off, on in POSIX mode
|
|Shell mode:|all|Default:|off, on in POSIX mode|
|
||||||
|
|
||||||
If set, the shift builtin prints an error message when the shift count
|
If set, the shift builtin prints an error message when the shift count
|
||||||
exceeds the number of positional parameters.
|
exceeds the number of positional parameters.
|
||||||
|
|
||||||
### sourcepath
|
### sourcepath
|
||||||
|
|
||||||
Option: `sourcepath` Since: unknown
|
|Option:|`sourcepath`|Since:|unknown|
|
||||||
------------- -------------- ---------- ---------
|
|-------|------------|------|-------|
|
||||||
Shell mode: all Default: on
|
|Shell mode:|all|Default:|on|
|
||||||
|
|
||||||
If set, the source builtin command uses the value of PATH to find the
|
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
|
directory containing the file supplied as an argument. This option is
|
||||||
@ -470,9 +469,9 @@ enabled by default.
|
|||||||
|
|
||||||
### syslog_history
|
### syslog_history
|
||||||
|
|
||||||
Option: `syslog_history` Since: 5.0-alpha
|
|Option:|`syslog_history`|Since:|5.0-alpha|
|
||||||
------------- ------------------ ---------- -----------
|
|-------|----------------|------|--------|
|
||||||
Shell mode: unknown Default: off
|
|Shell mode:|unknown|Default:|off|
|
||||||
|
|
||||||
If set, the shell history is sent to syslog.
|
If set, the shell history is sent to syslog.
|
||||||
|
|
||||||
@ -481,9 +480,9 @@ syslog.
|
|||||||
|
|
||||||
### xpg_echo
|
### xpg_echo
|
||||||
|
|
||||||
Option: `xpg_echo` Since: 2.04-beta1
|
|Option:|`xpg_echo`|Since:|2.04-beta1|
|
||||||
------------- ------------ ---------- ------------
|
|-------|----------|------|----------|
|
||||||
Shell mode: all Default: off
|
|Shell mode:|all|Default:|off|
|
||||||
|
|
||||||
If set, the `echo`-builtin command expands backslash-escape sequences by
|
If set, the `echo`-builtin command expands backslash-escape sequences by
|
||||||
default (POSIX, SUS, XPG).
|
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
|
here and there. Also, [another
|
||||||
snapshot](http://mywiki.wooledge.org/BashFAQ/064).
|
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
|
Our bashphorisms can be queried from `greybot` using `!bN`, where `N` is
|
||||||
the bashphorism number.
|
the bashphorism number.
|
||||||
|
|
||||||
And yes, these bashphorisms reflect the daily reality in `#bash`.
|
And yes, these bashphorisms reflect the daily reality in `#bash`.
|
||||||
|
|
||||||
Number Bashphorism
|
|Number|Bashphorism|
|
||||||
-------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|------|-----------|
|
||||||
0 The questioner will never tell you what they are really doing the first time they ask.
|
|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.
|
|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.
|
|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.
|
|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.
|
|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.
|
|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.
|
|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.\"
|
|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.
|
|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.
|
|9|All examples given by the questioner will be broken, misleading, wrong, and not representative of the actual question.|
|
||||||
10 See B1
|
|10|See B1|
|
||||||
11 Please apply `(( % 10 ))` to the bashphorism value.
|
|11|Please apply `(( % 10 ))` to the bashphorism value.|
|
||||||
12 All logic is deniable; however, some logic will \*plonk\* you if you deny it.
|
|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
|
|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.
|
|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.
|
|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.
|
|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.
|
|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.
|
|18|The newbie will not accept the answer you give, no matter how right it is.|
|
||||||
19 The newbie is a bloody loon.
|
|19|The newbie is a bloody loon.|
|
||||||
20 The newbie will always have some excuse for doing it wrong.
|
|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.
|
|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.
|
|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.
|
|23|Everyone is a newcomer.|
|
||||||
24 The newcomer will address greybot as if it were human.
|
|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.
|
|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.
|
|26|The newbie will not TELL you about this restriction until you have wasted half an hour.|
|
||||||
27 The newbie will lie.
|
|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.
|
|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.
|
|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.
|
|30|They won't show you the homework assignment. That would make it too easy.|
|
||||||
31 Your teacher is a f\*\*king idiot.
|
|31|Your teacher is a f**king idiot.|
|
||||||
32 The more horrifyingly wrong a proposed solution is, the more likely it will be used.
|
|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?!
|
|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.
|
Please feel free to correct or extend this page whenever needed.
|
||||||
|
@ -12,13 +12,14 @@ tags:
|
|||||||
|
|
||||||
# Bash's behaviour
|
# Bash's behaviour
|
||||||
|
|
||||||
FIXME incomplete
|
!!! warning "FIXME"
|
||||||
|
incomplete
|
||||||
|
|
||||||
## Bash startup modes
|
## Bash startup modes
|
||||||
|
|
||||||
### Login shell
|
### 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
|
from `/etc/profile` and one of `~/.bash_profile`, `~/.bash_login`, or
|
||||||
`~/.profile` (in that order, using the first one that's readable!).
|
`~/.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
|
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)
|
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
|
- the first character of `argv[0]` is `-` (a hyphen): traditional
|
||||||
UNIX(r) shells start from the `login` binary
|
UNIX(r) shells start from the `login` binary
|
||||||
- Bash is started with the `-l` option
|
- Bash is started with the `-l` option
|
||||||
- Bash is started with the `--login` 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
|
- the shell option `login_shell` is set
|
||||||
|
|
||||||
[**Related switches:**]{.underline}
|
<u>**Related switches:**</u>
|
||||||
|
|
||||||
- `--noprofile` disables reading of all profile files
|
- `--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
|
When Bash starts as an interactive non-login shell, it reads and
|
||||||
executes commands from `~/.bashrc`. This file should contain, for
|
executes commands from `~/.bashrc`. This file should contain, for
|
||||||
example, aliases, since they need to be defined in every shell as
|
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
|
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
|
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
|
system-wide rc file is to `source /etc/bashrc` from every user's
|
||||||
`~/.bashrc`.
|
`~/.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)
|
- the special parameter `$-` contains the letter `i` (lowercase I)
|
||||||
|
|
||||||
[**Related switches:**]{.underline}
|
<u>**Related switches:**</u>
|
||||||
|
|
||||||
- `-i` forces the interactive mode
|
- `-i` forces the interactive mode
|
||||||
- `--norc` disables reading of the startup files (e.g.
|
- `--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
|
After the startup files are read, Bash enters the [POSIX(r) compatiblity
|
||||||
mode (for running, not for starting!)](#posix_run_mode).
|
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
|
- 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
|
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
|
When Bash is started in POSIX(r) mode, it follows the POSIX(r) standard
|
||||||
for startup files. In this mode, **interactive shells** expand the
|
for startup files. In this mode, **interactive shells** expand the
|
||||||
[ENV](../syntax/shellvars.md#ENV) variable and commands are read and executed
|
[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
|
No other startup files are read. Hence, a non-interactive shell doesn't
|
||||||
read any startup files in POSIX(r) mode.
|
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 commandline option `--posix` is specified
|
||||||
- the environment variable
|
- 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
|
Bash usually reads the first file found, when multiple choices are
|
||||||
given (for user files in `~/`)
|
given (for user files in `~/`)
|
||||||
|
|
||||||
Mode `/etc/profile` `~/.bash_profile` `~/.bash_login` `~/.profile` `~/.bashrc` `${ENV}`
|
|Mode|`/etc/profile`|`~/.bash_profile`|`~/.bash_login`|`~/.profile`|`~/.bashrc`|`${ENV}`|
|
||||||
----------------------- ---------------- ------------------- ----------------- -------------- ------------- ----------
|
|--|--|--|--|--|--|--|
|
||||||
Login shell X X X X - -
|
|Login shell|✅|✅|✅|✅|🚫|🚫|
|
||||||
Interactive shell - - - - X -
|
|Interactive shell|🚫|🚫|🚫|🚫|✅|🚫|
|
||||||
SH compatible login X - - X - -
|
|SH compatible login|✅|🚫|🚫|✅|🚫|🚫|
|
||||||
SH compatible - - - - - X
|
|SH compatible|🚫|🚫|🚫|🚫|🚫|✅|
|
||||||
POSIX(r) compatiblity - - - - - X
|
|POSIX(r) compatiblity|🚫|🚫|🚫|🚫|🚫|✅|
|
||||||
|
|
||||||
## Bash run modes
|
## 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
|
Bash can be configured to be POSIX-conformant by default, by specifying
|
||||||
the `--enable-strict-posix-default' to `configure' when building.
|
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`)
|
- Bash starting as `sh` (the basename of `argv[0]` is `sh`)
|
||||||
- starting Bash with the commandline option `--posix`
|
- 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
|
[POSIXLY_CORRECT](../syntax/shellvars.md#POSIXLY_CORRECT) is set
|
||||||
- the command `set -o posix`
|
- 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
|
- the variable [SHELLOPTS](../syntax/shellvars.md#SHELLOPTS) contains
|
||||||
`posix` in its list
|
`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
|
[PATH](../syntax/shellvars.md#PATH), [ENV](../syntax/shellvars.md#ENV) and
|
||||||
[BASH_ENV](../syntax/shellvars.md#BASH_ENV) can't be set or unset
|
[BASH_ENV](../syntax/shellvars.md#BASH_ENV) can't be set or unset
|
||||||
- command names that contain a `/` (slash) can't be called (hence
|
- 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
|
- filenames containing a `/` (slash) can't be specified as argument
|
||||||
to the `source` or `.` builtin command
|
to the `source` or `.` builtin command
|
||||||
- filenames containing a `/` (slash) can't be specified as argument
|
- 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
|
- turning off restricted mode with `set +r` or `set +o restricted` is
|
||||||
(of course) forbidden
|
(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.
|
startup files.
|
||||||
|
|
||||||
When the command that is run is a shell script, then the restrictions
|
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.
|
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 as `rbash` (the basename of `argv[0]` is `rbash`)
|
||||||
- calling Bash with the `-r` option
|
- calling Bash with the `-r` option
|
||||||
- calling Bash with the `--restricted` 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 special parameter `$-` contains the letter `r` (lowercase R)
|
||||||
- the shell option `restricted_shell` is set and can be checked by the
|
- 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)
|
- [shell_options](../internals/shell_options.md)
|
||||||
- [set](../commands/builtin/set.md)
|
- [set](../commands/builtin/set.md)
|
||||||
|
|
||||||
Feature or change description Appeared in Bash version See also/remarks
|
|Feature or change description|Appeared in Bash version|See also/remarks|
|
||||||
--------------------------------- -------------------------- ---------------------------------------------------------------------------------
|
|--|--|--|
|
||||||
`posix` (for `set -o`) 1.14.0
|
|`posix` (for `set -o`)|1.14.0||
|
||||||
`hostcomplete` 2.0-alpha3
|
|`hostcomplete`|2.0-alpha3||
|
||||||
`expand_aliases` 2.0
|
|`expand_aliases`|2.0||
|
||||||
`huponexit` 2.02-alpha1
|
|`huponexit`|2.02-alpha1||
|
||||||
`nocaseglob` 2.02-alpha1
|
|`nocaseglob`|2.02-alpha1||
|
||||||
`extglob` 2.02-alpha1 together with extended globbing, KSH88
|
|`extglob`|2.02-alpha1|together with extended globbing, KSH88|
|
||||||
`restricted_shell` 2.03-alpha
|
|`restricted_shell`|2.03-alpha||
|
||||||
`xpg_echo` 2.04-beta1
|
|`xpg_echo`|2.04-beta1||
|
||||||
`progcomp` 2.04-alpha1
|
|`progcomp`|2.04-alpha1||
|
||||||
`no_empty_command_completion` 2.04
|
|`no_empty_command_completion`|2.04||
|
||||||
`login_shell` 2.05a-alpha1
|
|`login_shell`|2.05a-alpha1||
|
||||||
`nolog` (for `set -o`) 2.05a
|
|`nolog` (for `set -o`)|2.05a||
|
||||||
`gnu_errfmt` 3.0-alpha
|
|`gnu_errfmt`|3.0-alpha||
|
||||||
`force_fignore` 3.0-alpha
|
|`force_fignore`|3.0-alpha||
|
||||||
`failglob` 3.0-alpha
|
|`failglob`|3.0-alpha||
|
||||||
`extquote` 3.0-alpha unsure -- verify!
|
|`extquote`|3.0-alpha|unsure -- verify!|
|
||||||
`extdebug` 3.0-alpha
|
|`extdebug`|3.0-alpha||
|
||||||
`pipefail` (for `set -o`) 3.0
|
|`pipefail` (for `set -o`)|3.0||
|
||||||
`functrace` (for `set -o`) 3.0
|
|`functrace` (for `set -o`)|3.0||
|
||||||
`errtrace` (for `set -o`) 3.0
|
|`errtrace` (for `set -o`)|3.0||
|
||||||
`nocasematch` 3.1-alpha1
|
|`nocasematch`|3.1-alpha1||
|
||||||
`dirspell` 4.0-alpha
|
|`dirspell`|4.0-alpha||
|
||||||
`globstar` 4.0-alpha
|
|`globstar`|4.0-alpha||
|
||||||
`checkjobs` 4.0-alpha
|
|`checkjobs`|4.0-alpha||
|
||||||
`autocd` 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
|
|`set -e` effects more intuitive|4.0|not directly specified by POSIX, but in consensus with POSIX WG|
|
||||||
`compat40` 4.1-beta
|
|`compat40`|4.1-beta||
|
||||||
`lastpipe` 4.2-alpha only works with job control disabled
|
|`lastpipe`|4.2-alpha|only works with job control disabled|
|
||||||
`compat41` 4.2-alpha
|
|`compat41`|4.2-alpha||
|
||||||
`globasciiranges` 4.3-alpha enable \"character range globbing\" to always act as if in `C` locale
|
|`globasciiranges`|4.3-alpha|enable "character range globbing" to always act as if in `C` locale|
|
||||||
`compat42` 4.3-alpha
|
|`compat42`|4.3-alpha||
|
||||||
`compat43` 4.4-alpha
|
|`compat43`|4.4-alpha||
|
||||||
`compat44` 5.0-alpha
|
|`compat44`|5.0-alpha||
|
||||||
`localvar_inherit` 5.0-alpha local variables inherit preceeding scope values if they have the same name
|
|`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
|
|`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
|
|`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)
|
|`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
|
|`localvar_inherit`|5.0-beta|guard code against inheriting from an incompatible data type|
|
||||||
`checkwinsize` 5.0-beta2 New default: on
|
|`checkwinsize`|5.0-beta2|New default: on|
|
||||||
`shift_verbose` 5.0-beta2 Default on when in POSIX mode
|
|`shift_verbose`|5.0-beta2|Default on when in POSIX mode|
|
||||||
|
|
||||||
### General (all/many builtins)
|
### General (all/many builtins)
|
||||||
|
|
||||||
Feature or change description Appeared in Bash version See also/remarks
|
|Feature or change description|Appeared in Bash version|See also/remarks|
|
||||||
----------------------------------------------------------------------- -------------------------- -----------------------------------------------------------------
|
|--|--|--|
|
||||||
generally return 2 on usage error 2.0
|
|generally return 2 on usage error|2.0||
|
||||||
generally accept `--` (end of options) 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
|
|(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
|
### printf
|
||||||
|
|
||||||
@ -79,20 +79,20 @@ For this topic, see also
|
|||||||
|
|
||||||
- [printf](../commands/builtin/printf.md)
|
- [printf](../commands/builtin/printf.md)
|
||||||
|
|
||||||
Feature or change description Appeared in Bash version See also/remarks
|
|Feature or change description|Appeared in Bash version|See also/remarks|
|
||||||
------------------------------------------------------------- -------------------------- --------------------------------------------------------
|
|--|--|--|
|
||||||
new `printf` command 2.02-alpha1
|
|new `printf` command|2.02-alpha1||
|
||||||
respects `0..` and `0x..` prefixed numbers 2.04-beta1 consistency with arithmetic
|
|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) length specifiers `j`, `t` and `z`|2.05a-alpha1|ISO C99|
|
||||||
POSIX(r) flag `'` 2.05a-alpha1
|
|POSIX(r) flag `'`|2.05a-alpha1||
|
||||||
conversion `a` and `A` 2.05a-rc1 if provided by the underlying printf(3)
|
|conversion `a` and `A`|2.05a-rc1|if provided by the underlying printf(3)|
|
||||||
conversion `F` 2.05a-rc1
|
|conversion `F`|2.05a-rc1||
|
||||||
conversion `n` 2.05a-rc1
|
|conversion `n`|2.05a-rc1||
|
||||||
new option `-v` 3.1-alpha1
|
|new option `-v`|3.1-alpha1||
|
||||||
escape sequences `\"` and `\?` 3.0-beta1
|
|escape sequences `\"` and `\?`|3.0-beta1||
|
||||||
modified option `-v` to assign to individual array elements 4.1-alpha
|
|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
|
|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`, `$'...'`
|
|`\uNNNN` and `\UNNNNNNNN` escape sequences|4.2-alpha|for: `printf`, `echo -e`, `$'...'`|
|
||||||
|
|
||||||
### Conditional expressions and test command
|
### Conditional expressions and test command
|
||||||
|
|
||||||
@ -101,141 +101,141 @@ For this topic, see also
|
|||||||
- [conditional_expression](../syntax/ccmd/conditional_expression.md)
|
- [conditional_expression](../syntax/ccmd/conditional_expression.md)
|
||||||
- [classictest](../commands/classictest.md)
|
- [classictest](../commands/classictest.md)
|
||||||
|
|
||||||
Feature or change description Appeared in Bash version See also/remarks
|
|Feature or change description|Appeared in Bash version|See also/remarks|
|
||||||
-------------------------------------------------------------------- -------------------------- --------------------------------------------------------------------------------------
|
|--|--|--|
|
||||||
`test`: `-o`, `==`, `<` and `>` 2.0
|
|`test`: `-o`, `==`, `<` and `>`|2.0||
|
||||||
`test`: `-N` 2.02
|
|`test`: `-N`|2.02||
|
||||||
`[[...]]`: new 2.02-alpha1 KSH93
|
|`[[...]]`: new|2.02-alpha1|KSH93|
|
||||||
`[[...]]`: regex support (`=~`) 3.0-alpha
|
|`[[...]]`: regex support (`=~`)|3.0-alpha||
|
||||||
`[[...]]`: quotable right-hand-side of `=~` forces string matching 3.2-alpha for consistency with pattern matching
|
|`[[...]]`: 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)
|
|`[[...]]`: `<` 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|check if a variable is set|
|
||||||
`test`/`[`/`[[`: `-v` 4.2-alpha support array syntax to check for elements
|
|`test`/`[`/`[[`: `-v`|4.2-alpha|support array syntax to check for elements|
|
||||||
`test`/`[`/`[[`: `-N` accepts nanoseconds 5.1-alpha
|
|`test`/`[`/`[[`: `-N` accepts nanoseconds|5.1-alpha||
|
||||||
`test`/`[`/`[[`: `-v` accepts positional parameters 5.1-alpha
|
|`test`/`[`/`[[`: `-v` accepts positional parameters|5.1-alpha||
|
||||||
|
|
||||||
### Other builtins and keywords
|
### Other builtins and keywords
|
||||||
|
|
||||||
Builtin Feature or change description Appeared in Bash version See also/remarks
|
|Builtin|Feature or change description|Appeared in Bash version|See also/remarks|
|
||||||
----------------------- -------------------------------------------------------------------------------------------------------------------------------------------- -------------------------- -----------------------------------------------------------------------------------------------
|
|--|--|--|--|
|
||||||
`bashbug` new 1.14.0
|
|`bashbug`|new|1.14.0||
|
||||||
`select` new 1.14.0
|
|`select`|new|1.14.0||
|
||||||
`disown` new 2.0
|
|`disown`|new|2.0||
|
||||||
`shopt` new 2.0 [shopt](../commands/builtin/shopt.md)
|
|`shopt`|new|2.0|[shopt](../commands/builtin/shopt.md)|
|
||||||
`declare` new options `-a` and `-F` 2.0
|
|`declare`|new options `-a` and `-F`|2.0||
|
||||||
`enable` builtin has basic plugin support (dlopen) 2.0
|
|`enable`|builtin has basic plugin support (dlopen)|2.0||
|
||||||
`exec` options `-l`, `-c` and `-a` 2.0
|
|`exec`|options `-l`, `-c` and `-a`|2.0||
|
||||||
`read` options `-p`, `-e` and `-a` 2.0 [read](../commands/builtin/read.md)
|
|`read`|options `-p`, `-e` and `-a`|2.0|[read](../commands/builtin/read.md)|
|
||||||
`readonly` option `-a` 2.0 [arrays](../syntax/arrays.md)
|
|`readonly`|option `-a`|2.0|[arrays](../syntax/arrays.md)|
|
||||||
`time` new keyword 2.0
|
|`time`|new keyword|2.0||
|
||||||
`shopt` `-p` (reusable output) 2.02
|
|`shopt`|`-p` (reusable output)|2.02||
|
||||||
`umask` `-p` (reusable output) 2.02
|
|`umask`|`-p` (reusable output)|2.02||
|
||||||
`complete` new 2.04-devel for and together with support for programmable completion
|
|`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
|
|`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)
|
|`read`|options `-t`, `-n`, `-d`, `-s`|2.04-devel|[read](../commands/builtin/read.md)|
|
||||||
`for ((...;...;...))` new 2.04-devel KSH93
|
|`for ((...;...;...))`|new|2.04-devel|KSH93|
|
||||||
`set` print shell functions in a format reusable as input 2.05-beta1
|
|`set`|print shell functions in a format reusable as input|2.05-beta1||
|
||||||
`for` allow an empty word list 2.05a-alpha1
|
|`for`|allow an empty word list|2.05a-alpha1||
|
||||||
`read` new option `-u` 2.05b-alpha1 [read](../commands/builtin/read.md)
|
|`read`|new option `-u`|2.05b-alpha1|[read](../commands/builtin/read.md)|
|
||||||
`caller` new 3.0 [caller](../commands/builtin/caller.md)
|
|`caller`|new|3.0|[caller](../commands/builtin/caller.md)|
|
||||||
`coproc` new 4.0-alpha
|
|`coproc`|new|4.0-alpha||
|
||||||
`declare` new options `-l` and `-u` 4.0-alpha together with case-changing expansion forms
|
|`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)
|
|`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
|
|`read`|changed `-t` (fractional seconds)|4.0-alpha||
|
||||||
`mapfile` new 4.0-alpha
|
|`mapfile`|new|4.0-alpha||
|
||||||
`read` new option `-i` 4.0-alpha
|
|`read`|new option `-i`|4.0-alpha||
|
||||||
`compopt` new 4.0-alpha
|
|`compopt`|new|4.0-alpha||
|
||||||
`read` modified option `-t` to test for data 4.0-beta
|
|`read`|modified option `-t` to test for data|4.0-beta||
|
||||||
`read` new option `-N` 4.1-alpha
|
|`read`|new option `-N`|4.1-alpha||
|
||||||
`mapfile` changed behaviour regarding history spamming 4.1-alpha
|
|`mapfile`|changed behaviour regarding history spamming|4.1-alpha||
|
||||||
`declare` new option `-g` 4.2-alpha
|
|`declare`|new option `-g`|4.2-alpha||
|
||||||
`mapfile` calls the callback with an additional argument: The line (data) 4.2-alpha
|
|`mapfile`|calls the callback with an additional argument: The line (data)|4.2-alpha||
|
||||||
`cd` new option `-e` 4.2-alpha
|
|`cd`|new option `-e`|4.2-alpha||
|
||||||
`echo` `\uNNNN` and `\UNNNNNNNN` escape sequences 4.2-alpha for: `printf`, `echo -e`, `$'...'`
|
|`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
|
|`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
|
|`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
|
|`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
|
|`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
|
|`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
|
|`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
|
|`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
|
|`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
|
|`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
|
|`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
|
|`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
|
|`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
|
|`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
|
|`mapfile`|new option `-d`|4.4-alpha||
|
||||||
`wait` new option `-f` 5.0-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
|
|`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
|
|`umask`|allows modes greater than octal 777|5.0-alpha||
|
||||||
`times` honors current locale settings when printing decimal points 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)
|
|`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
|
|`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
|
|`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
|
|`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
|
|`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`|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
|
|`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
|
|`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
|
|`ulimit`|new option `-R` to get/set `RLIMIT_RTTIME` resource|5.1-alpha||
|
||||||
|
|
||||||
## Builtin variables
|
## Builtin variables
|
||||||
|
|
||||||
Feature or change description Appeared in Bash version See also
|
|Feature or change description|Appeared in Bash version|See also|
|
||||||
--------------------------------------------------- -------------------------- ----------------------------------------------------------------------------------
|
|--|--|--|
|
||||||
`HISTCMD` 1.14.0 interactive usage
|
|`HISTCMD`|1.14.0|interactive usage|
|
||||||
`PS1`, `PS2`, `PATH`, and `IFS` are unsettable 2.0
|
|`PS1`, `PS2`, `PATH`, and `IFS` are unsettable|2.0||
|
||||||
`DIRSTACK` array variable 2.0
|
|`DIRSTACK` array variable|2.0||
|
||||||
`PIPESTATUS` array variable 2.0
|
|`PIPESTATUS` array variable|2.0||
|
||||||
`BASH_VERSINFO` array variable 2.0
|
|`BASH_VERSINFO` array variable|2.0||
|
||||||
`HOSTNAME` 2.0
|
|`HOSTNAME`|2.0||
|
||||||
`SHELLOPTS` 2.0
|
|`SHELLOPTS`|2.0||
|
||||||
`MACHTYPE` 2.0
|
|`MACHTYPE`|2.0||
|
||||||
`GLOBIGNORE` 2.0
|
|`GLOBIGNORE`|2.0||
|
||||||
`HISTIGNORE` 2.0
|
|`HISTIGNORE`|2.0||
|
||||||
respect `LC_ALL` 2.0
|
|respect `LC_ALL`|2.0||
|
||||||
respect `LC_MESSAGES` 2.0
|
|respect `LC_MESSAGES`|2.0||
|
||||||
respect `LC_CTYPE` 2.0
|
|respect `LC_CTYPE`|2.0||
|
||||||
respect `LC_COLLATE` 2.0
|
|respect `LC_COLLATE`|2.0||
|
||||||
respect `LANG` 2.0
|
|respect `LANG`|2.0||
|
||||||
`GROUPS` array variable 2.01
|
|`GROUPS` array variable|2.01||
|
||||||
`GROUPS` unsettable/takes (discarded) assignments 2.04
|
|`GROUPS` unsettable/takes (discarded) assignments|2.04||
|
||||||
`FUNCNAME` 2.04
|
|`FUNCNAME`|2.04||
|
||||||
respect `LC_NUMERIC` 2.04
|
|respect `LC_NUMERIC`|2.04||
|
||||||
`TMOUT` 2.05b
|
|`TMOUT`|2.05b||
|
||||||
`BASH_REMATCH` 3.0 together with regex support in `[[...]]`
|
|`BASH_REMATCH`|3.0|together with regex support in `[[...]]`|
|
||||||
`BASH_ARGC` 3.0 debugger support
|
|`BASH_ARGC`|3.0|debugger support|
|
||||||
`BASH_ARGV` 3.0 debugger support
|
|`BASH_ARGV`|3.0|debugger support|
|
||||||
`BASH_SOURCE` 3.0 debugger support
|
|`BASH_SOURCE`|3.0|debugger support|
|
||||||
`BASH_LINENO` 3.0 debugger support
|
|`BASH_LINENO`|3.0|debugger support|
|
||||||
`BASH_SUBSHELL` 3.0 debugger support
|
|`BASH_SUBSHELL`|3.0|debugger support|
|
||||||
`BASH_EXECUTION_STRING` 3.0 debugger support
|
|`BASH_EXECUTION_STRING`|3.0|debugger support|
|
||||||
`BASH_COMMAND` 3.0 debugger support
|
|`BASH_COMMAND`|3.0|debugger support|
|
||||||
`HISTTIMEFORMAT` 3.0
|
|`HISTTIMEFORMAT`|3.0||
|
||||||
`COMP_WORDBREAKS` 3.0
|
|`COMP_WORDBREAKS`|3.0||
|
||||||
respect `LC_TIME` 3.1
|
|respect `LC_TIME`|3.1||
|
||||||
`BASHPID` 4.0-alpha Added to mksh R41.
|
|`BASHPID`|4.0-alpha|Added to mksh R41.|
|
||||||
`PROMPT_DIRTRIM` 4.0
|
|`PROMPT_DIRTRIM`|4.0||
|
||||||
`BASH_XTRACEFD` 4.1-alpha
|
|`BASH_XTRACEFD`|4.1-alpha||
|
||||||
`BASHOPTS` 4.1-alpha
|
|`BASHOPTS`|4.1-alpha||
|
||||||
`FUNCNEST` 4.2-alpha
|
|`FUNCNEST`|4.2-alpha||
|
||||||
`HISTSIZE` 4.3-alpha can be set to negative values for unlimited history length
|
|`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
|
|`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
|
|`CHILD_MAX`|4.3-alpha|max. number of exit status of children the shell remembers|
|
||||||
`BASH_COMPAT` 4.3-alpha set shell compatiblity levels
|
|`BASH_COMPAT`|4.3-alpha|set shell compatiblity levels|
|
||||||
`EPOCHSECONDS` 5.0-alpha expands to the time in seconds since Unix epoch
|
|`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
|
|`EPOCHREALTIME`|5.0-alpha|expands to the time in seconds since Unix epoch with microsecond granularity|
|
||||||
`BASH_ARGV0` 5.0-alpha get/set `$0`
|
|`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)
|
|`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
|
|`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)
|
|`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`
|
|`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
|
|`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`
|
|`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)
|
|`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)
|
|`RANDOM`|5.1-alpha|Assignment using arithmetic expressions (is nominally an integer variabnle)|
|
||||||
`LINENO` 5.1-alpha Not an integer variabe
|
|`LINENO`|5.1-alpha|Not an integer variabe|
|
||||||
|
|
||||||
## Quoting, expansions, substitutions and related
|
## Quoting, expansions, substitutions and related
|
||||||
|
|
||||||
@ -243,40 +243,40 @@ For this topic, see also
|
|||||||
|
|
||||||
- [pe](../syntax/pe.md).
|
- [pe](../syntax/pe.md).
|
||||||
|
|
||||||
Feature or change description Appeared in Bash version Remarks
|
|Feature or change description|Appeared in Bash version|Remarks|
|
||||||
------------------------------------------------------------------------------------------------------ -------------------------- ---------------------------------------------------------------------------------------------------------------
|
|--|--|--|
|
||||||
Support for integer-indexed arrays 2.0 relevant builtins also got array support
|
|Support for integer-indexed arrays|2.0|relevant builtins also got array support|
|
||||||
`${PARAMETER//PATTERN/REPLACEMENT}` 2.0
|
|`${PARAMETER//PATTERN/REPLACEMENT}`|2.0||
|
||||||
`${PARAMETER:OFFSET:LENGTH}` 2.0
|
|`${PARAMETER:OFFSET:LENGTH}`|2.0||
|
||||||
`${!PARAMETER}` (indirection) 2.0
|
|`${!PARAMETER}` (indirection)|2.0||
|
||||||
`$"..."` (localized strings) 2.0
|
|`$"..."` (localized strings)|2.0||
|
||||||
`$'...'` (ANSI-C-like strings) 2.0
|
|`$'...'` (ANSI-C-like strings)|2.0||
|
||||||
`\xNNN` in `$'...'` (and `echo -e`) 2.02-alpha1
|
|`\xNNN` in `$'...'` (and `echo -e`)|2.02-alpha1||
|
||||||
`$(< FILENAME)` (file content) 2.02-alpha1
|
|`$(< FILENAME)` (file content)|2.02-alpha1||
|
||||||
globbing (`fnmatch()`) capable of POSIX(r) character classes etc. 2.02-alpha1
|
|globbing (`fnmatch()`) capable of POSIX(r) character classes etc.|2.02-alpha1||
|
||||||
extended globbing 2.02-alpha1 KSH88
|
|extended globbing|2.02-alpha1|KSH88|
|
||||||
globbing inside array mass-assignment: `ARRAY=(*.txt)` 2.03-alpha
|
|globbing inside array mass-assignment: `ARRAY=(*.txt)`|2.03-alpha||
|
||||||
`$'...\'...'` escaped single quote inside ANSI-C-like strings 2.04-devel KSH93
|
|`$'...\'...'` escaped single quote inside ANSI-C-like strings|2.04-devel|KSH93|
|
||||||
`${!PREFIX*}` (parameter name expansion) 2.04 KSH93
|
|`${!PREFIX*}` (parameter name expansion)|2.04|KSH93|
|
||||||
`$'...'` expands `\cx` (Control-x) 2.05b
|
|`$'...'` expands `\cx` (Control-x)|2.05b||
|
||||||
`[:class:]` syntax for pattern matching 2.05b KSH93
|
|`[:class:]` syntax for pattern matching|2.05b|KSH93|
|
||||||
`${!ARRAY[@]}` (array index expansion) 3.0-alpha KSH93
|
|`${!ARRAY[@]}` (array index expansion)|3.0-alpha|KSH93|
|
||||||
`{x..y}` (range brace expansion) 3.0-alpha
|
|`{x..y}` (range brace expansion)|3.0-alpha||
|
||||||
`$'...'` expands `\xNNN` (Hexdigits) 3.0
|
|`$'...'` expands `\xNNN` (Hexdigits)|3.0||
|
||||||
`+=` operator for arrays and strings 3.1-alpha1
|
|`+=` 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
|
|`${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
|
|`${@:0:x}` includes `$0`|4.0-alpha||
|
||||||
Support for associative arrays 4.0-alpha relevant builtins also got associative array support
|
|Support for associative arrays|4.0-alpha|relevant builtins also got associative array support|
|
||||||
case modification operators for expansions 4.0-alpha
|
|case modification operators for expansions|4.0-alpha||
|
||||||
`{0x..0y}` (zeropadding brace expansion) 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
|
|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`, `$'...'`
|
|`\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]}`.
|
|`${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
|
|Word expansions like `${foo##bar}` understand indirect variable references|4.3-beta||
|
||||||
Transformations 4.4
|
|Transformations|4.4||
|
||||||
Process substitution now works in POSIX mode 5.1-alpha
|
|Process substitution now works in POSIX mode|5.1-alpha||
|
||||||
New transformations: `U`, `u`, `L` 5.1-alpha Case-transformation
|
|New transformations: `U`, `u`, `L`|5.1-alpha|Case-transformation|
|
||||||
New transformation: `K` 5.1-alpha Display associative arrays as key/value pairs
|
|New transformation: `K`|5.1-alpha|Display associative arrays as key/value pairs|
|
||||||
|
|
||||||
## Arithmetic
|
## Arithmetic
|
||||||
|
|
||||||
@ -285,15 +285,15 @@ For this topic, see also
|
|||||||
- [arith_expr](../syntax/arith_expr.md)
|
- [arith_expr](../syntax/arith_expr.md)
|
||||||
- [arith](../syntax/expansion/arith.md)
|
- [arith](../syntax/expansion/arith.md)
|
||||||
|
|
||||||
Feature or change description Appeared in Bash version Remarks
|
|Feature or change description|Appeared in Bash version|Remarks|
|
||||||
-------------------------------------------- -------------------------- -------------------------------------------
|
|--|--|--|
|
||||||
`((...))` 2.0-beta2 KSH93
|
|`((...))`|2.0-beta2|KSH93|
|
||||||
ternary operator 2.0
|
|ternary operator|2.0||
|
||||||
base 64 integer constants 2.0 the max. base before is unknown. Anybody?
|
|base 64 integer constants|2.0|the max. base before is unknown. Anybody?|
|
||||||
deprecated `$[...]` in favor of `$((...))` 2.0
|
|deprecated `$[...]` in favor of `$((...))`|2.0||
|
||||||
exponentiaition operator (`**`) 2.02-alpha1
|
|exponentiaition operator (`**`)|2.02-alpha1||
|
||||||
comma operator `EXPR,EXPR` 2.04-devel
|
|comma operator `EXPR,EXPR`|2.04-devel||
|
||||||
pre- and postfix operators 2.04-devel
|
|pre- and postfix operators|2.04-devel||
|
||||||
|
|
||||||
## Redirection and related
|
## Redirection and related
|
||||||
|
|
||||||
@ -301,33 +301,33 @@ For this topic, see also
|
|||||||
|
|
||||||
- [redirection](../syntax/redirection.md)
|
- [redirection](../syntax/redirection.md)
|
||||||
|
|
||||||
Feature or change description Appeared in Bash version Remarks
|
|Feature or change description|Appeared in Bash version|Remarks|
|
||||||
--------------------------------------------------------------------------------------- -------------------------- ---------
|
|--|--|--|
|
||||||
socket redirection (`/dev/tcp/`, `/dev/udp/`) 2.04-devel
|
|socket redirection (`/dev/tcp/`, `/dev/udp/`)|2.04-devel||
|
||||||
OS/filesystem-independent support for `/dev/std(in|out|err)` and `/dev/fd/*` 2.04
|
|OS/filesystem-independent support for `/dev/std(in|out|err)` and `/dev/fd/*`|2.04||
|
||||||
socket redirection accepts service names 2.05
|
|socket redirection accepts service names|2.05||
|
||||||
`[n]<&word-` and `[n]>&word-` FD-duplicate/closing 2.05b-alpha1 KSH93
|
|`[n]<&word-` and `[n]>&word-` FD-duplicate/closing|2.05b-alpha1|KSH93|
|
||||||
Here strings: `<<< WORD` 2.05b-alpha1
|
|Here strings: `<<< WORD`|2.05b-alpha1||
|
||||||
`|&` (synonym for `2>&1 |`) 4.0-alpha
|
|`|&` (synonym for `2>&1|`)|4.0-alpha||
|
||||||
`&>>` (equiv. to `>>FILE 2>&1`) 4.0-alpha
|
|`&>>` (equiv. to `>>FILE 2>&1`)|4.0-alpha||
|
||||||
`{varname}` style automatic file descriptor allocation 4.1-alpha ksh93
|
|`{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
|
|`{varname[idx]}` fd allocation accepts array subscripts and special-meaning variables|4.3-alpha|ksh93|
|
||||||
|
|
||||||
## Misc
|
## Misc
|
||||||
|
|
||||||
Feature or change description Appeared in Bash version See also/remarks
|
|Feature or change description|Appeared in Bash version|See also/remarks|
|
||||||
------------------------------------------------------------------------------------------------- -------------------------- ------------------------------------------------------------------------------------------------------------------------------------------
|
|--|--|--|
|
||||||
`DEBUG` trap 2.0
|
|`DEBUG` trap|2.0||
|
||||||
`ERR` trap 2.05a KSH93
|
|`ERR` trap|2.05a|KSH93|
|
||||||
Support for multibyte characters: Unicode / UTF8 2.05b
|
|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.
|
|`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
|
|`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
|
|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
|
|`[[...]]` 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
|
|ACL support for file status checks|4.1-alpha||
|
||||||
Assignment to negative array indices 4.3-alpha ksh93, zsh
|
|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
|
|`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
|
|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
|
|process substitution does not inherit the `v` flag|5.0-alpha||
|
||||||
`ERR` trap 5.0-alpha Reports more reliable line numbers
|
|`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
|
|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
|
#!/bin/echo
|
||||||
|
|
||||||
We don't need a script body here, as the file will never be interpreted
|
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,
|
and executed by "`echo`". You can see what the Operating System does,
|
||||||
it calls \"`/bin/echo`\" with the name of the executable file and
|
it calls "`/bin/echo`" with the name of the executable file and
|
||||||
following arguments.
|
following arguments.
|
||||||
|
|
||||||
$ /home/bash/bin/test testword hello
|
$ /home/bash/bin/test testword hello
|
||||||
/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
|
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
|
If the interpreter can be specified with arguments and how long it can
|
||||||
be is system-specific (see
|
be is system-specific (see
|
||||||
[#!-magic](http://www.in-ulm.de/~mascheck/various/shebang/)). When Bash
|
[#!-magic](http://www.in-ulm.de/~mascheck/various/shebang/)). When Bash
|
||||||
executes a file with a #!/bin/bash shebang, the shebang itself is
|
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.
|
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
|
Programs that don't ignore such lines, may not work as shebang driven
|
||||||
interpreters.
|
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),
|
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
|
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>
|
interpreter specified by the shebang. </WRAP>
|
||||||
|
|
||||||
**Additional note:** When you specify `#!/bin/sh` as shebang and that's
|
**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
|
#!/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 `env` utility must be located in /usr/bin/
|
||||||
- the needed `bash` binary must be located in `PATH`
|
- the needed `bash` binary must be located in `PATH`
|
||||||
@ -104,7 +104,7 @@ files*:
|
|||||||
- **stdout**: standard output
|
- **stdout**: standard output
|
||||||
- **stderr**: standard error 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
|
(keyboard), stdout and stderr as output files (screen). When calling
|
||||||
such a program, the invoking shell can change these filedescriptor
|
such a program, the invoking shell can change these filedescriptor
|
||||||
connections away from the terminal to any other file (see redirection).
|
connections away from the terminal to any other file (see redirection).
|
||||||
@ -179,8 +179,8 @@ else
|
|||||||
fi
|
fi
|
||||||
```
|
```
|
||||||
|
|
||||||
A common decision making command is \"`test`\" or its equivalent
|
A common decision making command is "`test`" or its equivalent
|
||||||
\"`[`\". But note that, when calling test with the name \"`[`\", the
|
"`[`". But note that, when calling test with the name "`[`", the
|
||||||
square brackets are not part of the shell syntax, the left bracket
|
square brackets are not part of the shell syntax, the left bracket
|
||||||
**is** the test command!
|
**is** the test command!
|
||||||
|
|
||||||
@ -194,7 +194,7 @@ fi
|
|||||||
|
|
||||||
Read more about [the test command](../commands/classictest.md)
|
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
|
This lets you execute a command based on whether or not the previous
|
||||||
command completed successfully:
|
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."
|
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.
|
so others can check the script execution.
|
||||||
|
|
||||||
## Comments
|
## Comments
|
||||||
|
|
||||||
In a larger, or complex script, it's wise to comment the code. 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:
|
(hashmark) and continue to the end of the line:
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
@ -226,7 +226,7 @@ All three syntactically correct.
|
|||||||
### Block commenting
|
### Block commenting
|
||||||
|
|
||||||
To temporarily disable complete blocks of code you would normally have
|
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)
|
comment. There's a little trick, using the pseudo command `:` (colon)
|
||||||
and input redirection. The `:` does nothing, it's a pseudo command, so
|
and input redirection. The `:` does nothing, it's a pseudo command, so
|
||||||
it does not care about standard input. In the following code example,
|
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.
|
it, effectively, the entire block was ignored.
|
||||||
|
|
||||||
The here-document-tag was quoted here **to avoid substitutions** in the
|
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
|
here-documents](../syntax/redirection.md#tag_heredoc) for more
|
||||||
|
|
||||||
## Variable scope
|
## Variable scope
|
||||||
|
|
||||||
In Bash, the scope of user variables is generally *global*. That means,
|
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\"
|
it does **not** matter whether a variable is set in the "main program"
|
||||||
or in a \"function\", the variable is defined everywhere.
|
or in a "function", the variable is defined everywhere.
|
||||||
|
|
||||||
Compare the following *equivalent* code snippets:
|
Compare the following *equivalent* code snippets:
|
||||||
|
|
||||||
@ -280,10 +280,10 @@ echo $myvariable
|
|||||||
```
|
```
|
||||||
|
|
||||||
In both cases, the variable `myvariable` is set and accessible from
|
In both cases, the variable `myvariable` is set and accessible from
|
||||||
everywhere in that script, both in functions and in the \"main
|
everywhere in that script, both in functions and in the "main
|
||||||
program\".
|
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**
|
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
|
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
|
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
|
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)!
|
in the process tree](../scripting/processtree.md)!
|
||||||
|
|
||||||
[^1]: under specific circumstances, also by the shell itself
|
[^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
|
## Use a unique name for your script
|
||||||
|
|
||||||
Do **not** name your script `test`, for example! *Why?* `test` is the
|
Do **not** name your script `test`, for example! *Why?* `test` is the
|
||||||
name of a UNIX(r)-command, and [most likely built into your
|
name of a UNIX(r)-command, and <u>most likely built into your
|
||||||
shell]{.underline} (it's a built-in in Bash) - so you won't be able to
|
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.
|
run a script with the name `test` in a normal way.
|
||||||
|
|
||||||
**Don't laugh!** This is a classic mistake :-)
|
**Don't laugh!** This is a classic mistake :-)
|
||||||
|
|
||||||
## Read the error messages
|
## Read the error messages
|
||||||
|
|
||||||
Many people come into IRC and ask something like *\"Why does my script
|
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
|
fail? I get an error!"*. And when you ask them what the error message
|
||||||
is, they don't even know. Beautiful.
|
is, they don't even know. Beautiful.
|
||||||
|
|
||||||
Reading and interpreting error messages is 50% of your job as debugger!
|
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
|
give you hints as to where to start debugging. **READ YOUR ERROR
|
||||||
MESSAGES!**
|
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
|
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.
|
log-snips here, just to show you that annoying fact.
|
||||||
|
|
||||||
## Use a good editor
|
## 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
|
- print commands to be executed to `stderr` as if they were read
|
||||||
from input (script file or keyboard)
|
from input (script file or keyboard)
|
||||||
- print everything **before** any ([substitution and
|
- 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`)
|
- `set -x` mode (`set -o xtrace`)
|
||||||
- print everything as if it were executed, after [substitution and
|
- print everything as if it were executed, after [substitution and
|
||||||
expansion](../syntax/expansion/intro.md) is applied
|
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
|
configurable file descriptor, rather than sdtout by setting the
|
||||||
[BASH_XTRACEFD](../syntax/shellvars.md#BASH_XTRACEFD) variable.
|
[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 commandline: `bash -vx ./myscript`
|
||||||
- from shebang (OS dependant): `#!/bin/bash -vx`
|
- from shebang (OS dependant): `#!/bin/bash -vx`
|
||||||
@ -116,9 +116,9 @@ That fails. Why? Let's see the `xtrace` output:
|
|||||||
|
|
||||||
+ '[' bar baz = test ']'
|
+ '[' 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
|
separate words (which you would have realized if you READ THE ERROR
|
||||||
MESSAGES ;) ). Let's check it\...
|
MESSAGES ;) ). Let's check it...
|
||||||
|
|
||||||
# next try
|
# next try
|
||||||
[ "$foo" = test ]
|
[ "$foo" = test ]
|
||||||
@ -146,7 +146,7 @@ function*:
|
|||||||
|
|
||||||
+(somefile.bash:412): echo 'Hello world'
|
+(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'
|
+(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 `}`?
|
||||||
- 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
|
`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
|
there is an EOF before the end-of-here-document tag (see
|
||||||
[redirection](../syntax/redirection.md)). The reason is unknown, but it seems
|
[redirection](../syntax/redirection.md)). The reason is unknown, but it seems
|
||||||
to be deliberate. Bash 4.0 added an extra message for this:
|
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>') ``
|
`` 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 50: unexpected EOF while looking for matching `"'
|
||||||
script.sh: line 100: syntax error: unexpected end of file
|
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**
|
such an error message though in our example, it was the **internal**
|
||||||
test-command that yielded the error.
|
test-command that yielded the error.
|
||||||
|
|
||||||
### !\": event not found
|
### !": event not found
|
||||||
|
|
||||||
$ echo "Hello world!"
|
$ echo "Hello world!"
|
||||||
bash: !": event not found
|
bash: !": event not found
|
||||||
|
|
||||||
This is not an error per se. It happens in interactive shells, when the
|
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:
|
the default. Disable it like this:
|
||||||
|
|
||||||
set +H
|
set +H
|
||||||
@ -317,8 +317,8 @@ CRs are a pain.
|
|||||||
Some possible sources of CRs:
|
Some possible sources of CRs:
|
||||||
|
|
||||||
- a DOS/Windows text editor
|
- a DOS/Windows text editor
|
||||||
- a UNIX(r) text editor that is \"too smart\" when determining the
|
- a UNIX(r) text editor that is "too smart" when determining the
|
||||||
file content type (and thinks \"*it's a DOS text file*\")
|
file content type (and thinks "*it's a DOS text file*")
|
||||||
- a direct copy and paste from certain webpages (some pastebins are
|
- a direct copy and paste from certain webpages (some pastebins are
|
||||||
known for this)
|
known for this)
|
||||||
|
|
||||||
@ -343,7 +343,7 @@ Here's what happens because of the `#!/bin/bash^M` in our shebang:
|
|||||||
problem.
|
problem.
|
||||||
- the script can't be executed
|
- 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
|
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
|
to the beginning of the line. The whole error message is *printed*, but
|
||||||
you *see* only part of it!
|
you *see* only part of it!
|
||||||
|
|
||||||
<note warning> It's easy to imagine the `^M` is bad in other places
|
!!! warning "warning"
|
||||||
too. If you get weird and illogical messages from your script, rule out
|
It's easy to imagine the `^M` is bad in other places
|
||||||
the possibility that`^M` is involved. Find and eliminate it! </note>
|
too. If you get weird and illogical messages from your script, rule out
|
||||||
|
the possibility that`^M` is involved. Find and eliminate it!
|
||||||
|
|
||||||
### How can I find and eliminate them?
|
### 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`)
|
- [the set builtin command](../commands/builtin/set.md) (for `-v` and `-x`)
|
||||||
|
|
||||||
FIXME
|
!!! warning "FIXME"
|
||||||
|
tbd.
|
||||||
|
|
||||||
- DEBUG trap
|
- DEBUG trap
|
||||||
- BASH Debugger <http://bashdb.sourceforge.net/>
|
- BASH Debugger <http://bashdb.sourceforge.net/>
|
||||||
|
@ -17,8 +17,8 @@ Here are some typical traps:
|
|||||||
### Your perfect Bash script executes with syntax errors
|
### Your perfect Bash script executes with syntax errors
|
||||||
|
|
||||||
If you write Bash scripts with Bash specific syntax and features, run
|
If you write Bash scripts with Bash specific syntax and features, run
|
||||||
them with [Bash]{.underline}, and run them with Bash in [native
|
them with <u>Bash</u>, and run them with Bash in <u>native
|
||||||
mode]{.underline}.
|
mode</u>.
|
||||||
|
|
||||||
**Wrong**:
|
**Wrong**:
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ See also:
|
|||||||
- [Bash startup mode: SH mode](../scripting/bashbehaviour.md#sh_mode)
|
- [Bash startup mode: SH mode](../scripting/bashbehaviour.md#sh_mode)
|
||||||
- [Bash run mode: POSIX mode](../scripting/bashbehaviour.md#posix_run_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.
|
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.
|
Some syntax elements have a BASH-specific, and a portable[^1]) pendant.
|
||||||
In these cases the portable syntax should be preferred.
|
In these cases the portable syntax should be preferred.
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|construct|portable equivalent|Description|Portability|
|
||||||
construct portable equivalent Description Portability
|
|---------|-------------------|-----------|-----------|
|
||||||
------------------------------------------ --------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -----------------------------------------------
|
|`source FILE`|`. FILE`|include a script file|Bourne shell (bash, ksh, POSIX(r), zsh, …)|
|
||||||
`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)|
|
||||||
`declare`\\ keyword `typeset` keyword define local variables (or variables with special attributes) ksh, zsh, \..., **not POSIX!**
|
|`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|
|
||||||
`command\ <<<\ WORD` `command <<MARKER WORD MARKER` a here-string, a special form of the here-document, avoid it in portable scripts! POSIX(r)
|
|`[[ 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|
|
||||||
`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, \...
|
|`((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|
|
||||||
|
|
||||||
`(( 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
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
## Portability rationale
|
## 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
|
about how which shell technically forks off which subshell). It's just
|
||||||
an assorted small set of portability guidelines. *-Thebonsai*
|
an assorted small set of portability guidelines. *-Thebonsai*
|
||||||
|
|
||||||
FIXME UNIX shell gurus out there, please be patient with a newbie like
|
!!! warning "FIXME"
|
||||||
me and give comments and hints instead of flames.
|
UNIX shell gurus out there, please be patient with a newbie like me
|
||||||
|
and give comments and hints instead of flames.
|
||||||
|
|
||||||
### Environment (exported) variables
|
### Environment (exported) variables
|
||||||
|
|
||||||
@ -100,7 +90,7 @@ Why? (list of known behaviours)
|
|||||||
- may or may not automatically interpret backslash escpape codes in
|
- may or may not automatically interpret backslash escpape codes in
|
||||||
the strings
|
the strings
|
||||||
- may or may not automatically interpret switches (like `-n`)
|
- 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
|
- `echo -n` and `echo -e` are neither portable nor standard (**even
|
||||||
within the same shell**, depending on the version or environment
|
within the same shell**, depending on the version or environment
|
||||||
variables or the build options, especially KSH93 and Bash)
|
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:x:x}` is KSH93/Bash specific
|
||||||
- `${var/../..}` and `${var//../..}` are KSH93/Bash specific
|
- `${var/../..}` and `${var//../..}` are KSH93/Bash specific
|
||||||
- `var=$*` and `var=$@` are not handled the same in all shells if the
|
- `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)
|
(except the Bourne shell always joins the expansions with space)
|
||||||
|
|
||||||
### Special variables
|
### Special variables
|
||||||
@ -130,11 +120,11 @@ of your script:
|
|||||||
#### RANDOM
|
#### RANDOM
|
||||||
|
|
||||||
[RANDOM](../syntax/shellvars.md#RANDOM) is Bash/KSH/ZSH specific variable
|
[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
|
other available external options, you can use awk to generate a random
|
||||||
number. There are multiple implementations of awk and which version your
|
number. There are multiple implementations of awk and which version your
|
||||||
system uses will depend. Most modern systems will call \'gawk\' (i.e.
|
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
|
GNU awk) or 'nawk'. 'oawk' (i.e. Original/Old awk) does not have the
|
||||||
rand() or srand() functions, so is best avoided.
|
rand() or srand() functions, so is best avoided.
|
||||||
|
|
||||||
# 'gawk' can produce random numbers using srand(). In this example, 10 integers between 1 and 500:
|
# '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)
|
# '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)} }')
|
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!*
|
complaining about possible stupid code!*
|
||||||
|
|
||||||
# Well, seeing how this //is// BASH-hackers.org I kinda missed the bash way of doing the above ;-)
|
# 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
|
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
|
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.
|
executability.
|
||||||
|
|
||||||
However, this method doesn't look nice. There are other ways of doing
|
However, this method doesn't look nice. There are other ways of doing
|
||||||
@ -207,6 +197,6 @@ accessible by `PATH`:
|
|||||||
echo "sed is available"
|
echo "sed is available"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
[^1]: \"portable\" doesn't necessarily mean it's POSIX, it can also
|
[^1]: "portable" doesn't necessarily mean it's POSIX, it can also
|
||||||
mean it's \"widely used and accepted\", and thus maybe more
|
mean it's "widely used and accepted", and thus maybe more
|
||||||
portable than POSIX(r
|
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
|
beyond the scope of this page. See the [portability
|
||||||
page](../scripting/nonportable.md) for a discussion on portability issues.
|
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
|
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
|
any legitimate uses. These features exist mostly for Bourne, csh, or
|
||||||
some other backward compatibility with obsolete shells, or were
|
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
|
None of the items on this list are specified by the most current version
|
||||||
of POSIX, and some may be incompatible with POSIX.
|
of POSIX, and some may be incompatible with POSIX.
|
||||||
|
|
||||||
Syntax Replacement Description
|
|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\`
|
|`&>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).
|
|`$[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.
|
|`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.
|
|`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.
|
|`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
|
This table lists syntax that is specified by POSIX (unless otherwise
|
||||||
specified below), but has been superseded by superior alternatives
|
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
|
are specified by POSIX may be badly designed and unchangeable for
|
||||||
historical reasons.
|
historical reasons.
|
||||||
|
|
||||||
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|Syntax|Replacement|Description|
|
||||||
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)*|
|
||||||
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)*
|
|``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)*.
|
# Frequently misued
|
||||||
|
|
||||||
`[\ 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`
|
|
||||||
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
This table lists features that are used only if you have a specific
|
This table lists features that are used only if you have a specific
|
||||||
reason to prefer it over another alternative. These have some legitimate
|
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
|
portability requirements, or in order to make use of some subtle
|
||||||
behavioral differences. These are frequently (mis)used for no reason.
|
behavioral differences. These are frequently (mis)used for no reason.
|
||||||
Writing portable scripts that go outside of POSIX features requires
|
Writing portable scripts that go outside of POSIX features requires
|
||||||
knowing how to account for many (often undocumented) differences across
|
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.
|
surprised if you run across someone telling you not to use these.
|
||||||
|
|
||||||
Syntax Replacement Description
|
|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)
|
|`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.
|
|`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)
|
|`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: [eval](../commands/builtin/eval.md) and [Eval command and security issues](http://mywiki.wooledge.org/BashFAQ/048).
|
|`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
|
## 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
|
arguments are known as **positional parameters**. Some relevant special
|
||||||
parameters are described below:
|
parameters are described below:
|
||||||
|
|
||||||
Parameter(s) Description
|
|Parameter(s)|Description|
|
||||||
------------------ ------------------------------------------------------------------------------------------------------------------------------------
|
|------------|-----------|
|
||||||
`$0` the first positional parameter, equivalent to `argv[0]` in C, see [the first argument](../scripting/posparams.md#the_first_argument)
|
|`$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)
|
|`$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
|
|`$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!)
|
|`${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)|
|
||||||
`$@` 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`
|
|`$#`|the number of arguments, not counting `$0`|
|
||||||
|
|
||||||
These positional parameters reflect exactly what was given to the script
|
These positional parameters reflect exactly what was given to the script
|
||||||
when it was called.
|
when it was called.
|
||||||
@ -33,8 +33,7 @@ when it was called.
|
|||||||
Option-switch parsing (e.g. `-h` for displaying help) is not performed
|
Option-switch parsing (e.g. `-h` for displaying help) is not performed
|
||||||
at this point.
|
at this point.
|
||||||
|
|
||||||
See also [the dictionary entry for
|
See also [the dictionary entry for "parameter"](../dict/parameter.md).
|
||||||
\"parameter\"](../dict/parameter.md).
|
|
||||||
|
|
||||||
## The first argument
|
## 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
|
usually set to the script's name exactly as called, and it's set on
|
||||||
shell initialization:
|
shell initialization:
|
||||||
|
|
||||||
[Testscript]{.underline} - it just echos `$0`:
|
<u>Testscript</u> - it just echos `$0`:
|
||||||
|
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
echo "$0"
|
echo "$0"
|
||||||
|
|
||||||
You see, `$0` is always set to the name the script is called with (`>`
|
You see, `$0` is always set to the name the script is called with (`>`
|
||||||
is the prompt\...):
|
is the prompt...):
|
||||||
|
|
||||||
> ./testscript
|
> ./testscript
|
||||||
./testscript
|
./testscript
|
||||||
@ -79,7 +78,7 @@ values:
|
|||||||
- `$1` will be discarded
|
- `$1` will be discarded
|
||||||
- `$2` will become `$1`
|
- `$2` will become `$1`
|
||||||
- `$3` will become `$2`
|
- `$3` will become `$2`
|
||||||
- \...
|
- ...
|
||||||
- in general: `$N` will become `$N-1`
|
- in general: `$N` will become `$N-1`
|
||||||
|
|
||||||
The command can take a number as argument: Number of positions to shift.
|
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"
|
echo "$arg"
|
||||||
done
|
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
|
### 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
|
to another program. It's very inefficient to do that in one of these
|
||||||
loops, as you will destroy integrity, most likely (spaces!).
|
loops, as you will destroy integrity, most likely (spaces!).
|
||||||
|
|
||||||
@ -180,27 +179,27 @@ The shell developers created `$*` and `$@` for this purpose.
|
|||||||
|
|
||||||
As overview:
|
As overview:
|
||||||
|
|
||||||
Syntax Effective result
|
|Syntax|Effective result|
|
||||||
-------- -----------------------------
|
|-------|----------------------------|
|
||||||
`$*` `$1 $2 $3 ... ${N}`
|
|`$*`|`$1 $2 $3 ... ${N}`|
|
||||||
`$@` `$1 $2 $3 ... ${N}`
|
|`$@`|`$1 $2 $3 ... ${N}`|
|
||||||
`"$*"` `"$1c$2c$3c...c${N}"`
|
|`"$*"`|`"$1c$2c$3c...c${N}"`|
|
||||||
`"$@"` `"$1" "$2" "$3" ... "${N}"`
|
|`"$@"`|`"$1" "$2" "$3" ... "${N}"`|
|
||||||
|
|
||||||
Without being quoted (double quotes), both have the same effect: All
|
Without being quoted (double quotes), both have the same effect: All
|
||||||
positional parameters from `$1` to the last one used are expanded
|
positional parameters from `$1` to the last one used are expanded
|
||||||
without any special handling.
|
without any special handling.
|
||||||
|
|
||||||
When the `$*` special parameter is double quoted, it expands to the
|
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`.
|
character of `IFS`.
|
||||||
|
|
||||||
But when the `$@` special parameter is used inside double quotes, it
|
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"`
|
`"$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
|
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
|
your positional parameters to **call another program** (for example in a
|
||||||
wrapper-script), then this is the choice for you, use double quoted
|
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
|
`COUNT` may not be negative, i.e. the element count may not be
|
||||||
decremented.
|
decremented.
|
||||||
|
|
||||||
[**Example:**]{.underline} START at the last positional parameter:
|
<u>**Example:**</u> START at the last positional parameter:
|
||||||
|
|
||||||
echo "${@: -1}"
|
echo "${@: -1}"
|
||||||
|
|
||||||
[**Attention**]{.underline}: As of Bash 4, a `START` of `0` includes the
|
<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,
|
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
|
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`.
|
`$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
|
Setting positional parameters with command line arguments, is not the
|
||||||
only way to set them. The [builtin command, set](../commands/builtin/set.md)
|
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:
|
inside the script or function:
|
||||||
|
|
||||||
set "This is" my new "set of" positional parameters
|
set "This is" my new "set of" positional parameters
|
||||||
@ -260,7 +259,7 @@ inside the script or function:
|
|||||||
# $5: positional
|
# $5: positional
|
||||||
# $6: parameters
|
# $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
|
parameters this way. If not, the dashes might be interpreted as an
|
||||||
option switch by `set` itself:
|
option switch by `set` itself:
|
||||||
|
|
||||||
@ -273,7 +272,8 @@ flags, which may otherwise be reset by `set`
|
|||||||
|
|
||||||
set -$- ...
|
set -$- ...
|
||||||
|
|
||||||
FIXME continue
|
!!! warning "FIXME"
|
||||||
|
continue
|
||||||
|
|
||||||
## Production examples
|
## Production examples
|
||||||
|
|
||||||
@ -281,7 +281,7 @@ FIXME continue
|
|||||||
|
|
||||||
To make your program accept options as standard command syntax:
|
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
|
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
|
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
|
This simple wrapper enables filtering unwanted options (here: `-a` and
|
||||||
`--all` for `ls`) out of the command line. It reads the positional
|
`--all` for `ls`) out of the command line. It reads the positional
|
||||||
parameters and builds a filtered array consisting of them, then calls
|
parameters and builds a filtered array consisting of them, then calls
|
||||||
`ls` with the new option set. It also respects the `--` as \"end of
|
`ls` with the new option set. It also respects the `--` as "end of
|
||||||
options\" for `ls` and doesn't change anything after it:
|
options" for `ls` and doesn't change anything after it:
|
||||||
|
|
||||||
#!/bin/bash
|
#!/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
|
responsible, for it. Every process has its own **context memory** (Not
|
||||||
the memory where the process stores its data, rather, the memory where
|
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
|
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.
|
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
|
`LANG`, for example, is used by every program that looks it up in its
|
||||||
environment to determinate the current locale.
|
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
|
`MYVAR=Hello`, is **not** automatically part of the environment. You
|
||||||
need to put it into the environment with the bash builtin command
|
need to put it into the environment with the bash builtin command
|
||||||
`export`:
|
`export`:
|
||||||
@ -41,30 +41,30 @@ set by login scripts or programs).
|
|||||||
|
|
||||||
## Executing programs
|
## Executing programs
|
||||||
|
|
||||||
All the diagrams of the process tree use names like \"`xterm`\" or
|
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
|
"`bash`", but that's just to make it easier to understand what's
|
||||||
going on, it doesn't mean those processes are actually executed.
|
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\"
|
Let's take a short look at what happens when you "execute a program"
|
||||||
from the Bash prompt, a program like \"ls\":
|
from the Bash prompt, a program like "ls":
|
||||||
|
|
||||||
$ ls
|
$ ls
|
||||||
|
|
||||||
Bash will now perform **two steps**:
|
Bash will now perform **two steps**:
|
||||||
|
|
||||||
- It will make a copy of itself
|
- 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: All environment variables will also be copied to the new
|
||||||
process. This step is called **forking**.
|
process. This step is called **forking**.
|
||||||
|
|
||||||
For a short moment, you have a process tree that might look like
|
For a short moment, you have a process tree that might look like
|
||||||
this\...
|
this...
|
||||||
|
|
||||||
xterm ----- bash ----- bash(copy)
|
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
|
`ls` program (the copy execs it), it might look like
|
||||||
|
|
||||||
xterm ----- bash ----- ls
|
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
|
The copy of the environment from the first step (forking) becomes the
|
||||||
environment for the final running program (in this case, `ls`).
|
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
|
the program `ls` does inside its own environment, it can't affect the
|
||||||
environment of its parent process (in this case, `bash`). 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.
|
to the parent environment when `ls` terminates.
|
||||||
|
|
||||||
## Bash playing with pipes
|
## 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
|
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
|
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,
|
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
|
$ 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
|
can't influence the `ls` environment, and neither `grep` nor `ls` can
|
||||||
influence the `bash` environment.
|
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,
|
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
|
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
|
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
|
a charm. It will also set the variable `counter` as directed. But if
|
||||||
everything ends, this extra process will be terminated - **your
|
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!
|
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
|
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
|
counter=0
|
||||||
|
|
||||||
@ -185,4 +185,5 @@ pipe in the command substitution:
|
|||||||
xterm ----- bash ----- bash (cmd. subst.) --|
|
xterm ----- bash ----- bash (cmd. subst.) --|
|
||||||
+-- wc -l
|
+-- wc -l
|
||||||
|
|
||||||
FIXME to be continued
|
!!! warning "FIXME"
|
||||||
|
to be continued
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
# Scripting with style
|
# Scripting with style
|
||||||
|
|
||||||
FIXME continue
|
!!! warning "FIXME"
|
||||||
|
continue
|
||||||
|
|
||||||
These are some coding guidelines that helped me to read and understand
|
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
|
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
|
will be a bit more robust than "if something breaks, I know how to fix
|
||||||
it\".
|
it".
|
||||||
|
|
||||||
This is not a bible, of course. But I have seen so much ugly and
|
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
|
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
|
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
|
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
|
Indentation is nothing that technically influences a script, it's only
|
||||||
for us humans.
|
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):
|
many may prefer 4 spaces, see below in the discussion section):
|
||||||
|
|
||||||
- it's easy and fast to type
|
- 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
|
waste too much space on the line
|
||||||
|
|
||||||
Speaking of hard-tabs: Avoid them if possible. They only make trouble. I
|
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).
|
[here-documents](../syntax/redirection.md#here_documents).
|
||||||
|
|
||||||
### Breaking up lines
|
### 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
|
Whenever you need to break lines of long code, you should follow one of
|
||||||
these two rules:
|
these two rules:
|
||||||
|
|
||||||
[**Indention using command width:**]{.underline}
|
<u>**Indention using command width:**</u>
|
||||||
|
|
||||||
activate some_very_long_option \
|
activate some_very_long_option \
|
||||||
some_other_option
|
some_other_option
|
||||||
|
|
||||||
[**Indention using two spaces:**]{.underline}
|
<u>**Indention using two spaces:**</u>
|
||||||
|
|
||||||
activate some_very_long_option \
|
activate some_very_long_option \
|
||||||
some_other_option
|
some_other_option
|
||||||
|
|
||||||
Personally, with some exceptions, I prefer the first form because it
|
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
|
### Breaking compound commands
|
||||||
|
|
||||||
[Compound commands](../syntax/ccmd/intro.md) form the structures that make a
|
[Compound commands](../syntax/ccmd/intro.md) form the structures that make a
|
||||||
shell script different from a stupid enumeration of commands. Usually
|
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.
|
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):
|
the basic idea):
|
||||||
|
|
||||||
- put the introducing keyword and the initial command list or
|
- put the introducing keyword and the initial command list or
|
||||||
parameters on one line (\"head\")
|
parameters on one line ("head")
|
||||||
- put the \"body-introducing\" keyword on the same line
|
- put the "body-introducing" keyword on the same line
|
||||||
- the command list of the \"body\" on separate lines, indented by two
|
- the command list of the "body" on separate lines, indented by two
|
||||||
spaces
|
spaces
|
||||||
- put the closing keyword on a separated line, indented like the
|
- put the closing keyword on a separated line, indented like the
|
||||||
initial introducing keyword
|
initial introducing keyword
|
||||||
@ -82,7 +83,7 @@ What?! Well, here again:
|
|||||||
##### if/then/elif/else
|
##### if/then/elif/else
|
||||||
|
|
||||||
This construct is a bit special, because it has keywords (`elif`,
|
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:
|
like this:
|
||||||
|
|
||||||
if ...; then
|
if ...; then
|
||||||
@ -110,7 +111,7 @@ like this:
|
|||||||
The `case` construct might need a bit more discussion here, since its
|
The `case` construct might need a bit more discussion here, since its
|
||||||
structure is a bit more complex.
|
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
|
case $input in
|
||||||
hello)
|
hello)
|
||||||
@ -149,13 +150,13 @@ It's - just like in C - the middle ground between smart, efficient and
|
|||||||
readable.
|
readable.
|
||||||
|
|
||||||
If you need to use a cryptic construct, include a comment that explains
|
If you need to use a cryptic construct, include a comment that explains
|
||||||
what your \"monster\" does.
|
what your "monster" does.
|
||||||
|
|
||||||
### Variable names
|
### Variable names
|
||||||
|
|
||||||
Since all reserved variables are `UPPERCASE`, the safest way is to only
|
Since all reserved variables are `UPPERCASE`, the safest way is to only
|
||||||
use `lowercase` variable names. This is true for reading user input,
|
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
|
- prefer `lowercase` variables
|
||||||
- if you use `UPPERCASE` names, **do not use reserved variable names**
|
- 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
|
- if you use `UPPERCASE` names, prepend the name with a unique prefix
|
||||||
(`MY_` in the example below)
|
(`MY_` in the example below)
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# the prefix 'MY_'
|
# the prefix 'MY_'
|
||||||
@ -200,7 +198,7 @@ in-code documentation for them.
|
|||||||
|
|
||||||
### Parameter expansion
|
### 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**.
|
expansion**.
|
||||||
|
|
||||||
There are some cases where this isn't needed from a technical point of
|
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`
|
- variable assignment: `VAR=$WORD`
|
||||||
|
|
||||||
But quoting these is never a mistake. If you quote every parameter
|
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,
|
If you need to parse a parameter as a list of words, you can't quote,
|
||||||
of course, e.g.
|
of course, e.g.
|
||||||
@ -252,8 +250,8 @@ should quote the command substitution!
|
|||||||
|
|
||||||
### Eval
|
### Eval
|
||||||
|
|
||||||
Well, like Greg says: **\"If eval is the answer, surely you are asking
|
Well, like Greg says: **"If eval is the answer, surely you are asking
|
||||||
the wrong question.\"**
|
the wrong question."**
|
||||||
|
|
||||||
Avoid it, unless absolutely neccesary:
|
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
|
- if possible, re-think the way your script works, if it seems you
|
||||||
can't avoid `eval` with your current method
|
can't avoid `eval` with your current method
|
||||||
- if you really, really, have to use it, then take care, and be sure
|
- 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
|
## 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
|
If possible (I know it's not always possible!), use a
|
||||||
[shebang](../dict/interpreter_directive.md).
|
[shebang](../dict/interpreter_directive.md).
|
||||||
|
|
||||||
Be careful with `/bin/sh`: The argument that \"on Linux `/bin/sh` is
|
Be careful with `/bin/sh`: The argument that "on Linux `/bin/sh` is
|
||||||
Bash\" **is a lie** (and technically irrelevant)
|
Bash" **is a lie** (and technically irrelevant)
|
||||||
|
|
||||||
The shebang serves two purposes for me:
|
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`!
|
called directly: If you code for Bash, specify `bash`!
|
||||||
- it documents the desired interpreter (so: use `bash` when you write
|
- it documents the desired interpreter (so: use `bash` when you write
|
||||||
a Bash-script, use `sh` when you write a general Bourne/POSIX
|
a Bash-script, use `sh` when you write a general Bourne/POSIX
|
||||||
script, \...)
|
script, ...)
|
||||||
|
|
||||||
### Configuration variables
|
### Configuration variables
|
||||||
|
|
||||||
I call variables that are meant to be changed by the user
|
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
|
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
|
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.
|
`lowercase` will be the safest.
|
||||||
|
|
||||||
### Function definitions
|
### Function definitions
|
||||||
@ -310,7 +308,7 @@ overview and ensures that all function names are known before they are
|
|||||||
used.
|
used.
|
||||||
|
|
||||||
Since a function isn't parsed before it is executed, you usually don't
|
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
|
The portable form of the function definition should be used, without the
|
||||||
`function` keyword (here using the [grouping compound
|
`function` keyword (here using the [grouping compound
|
||||||
@ -336,7 +334,7 @@ begins its work in a potentially broken state.
|
|||||||
### Availability of commands
|
### Availability of commands
|
||||||
|
|
||||||
If you use external commands that may not be present on the path, or not
|
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.
|
missing.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
@ -370,9 +368,9 @@ means:
|
|||||||
This, **and only this**, will enable the calling component to check the
|
This, **and only this**, will enable the calling component to check the
|
||||||
operation status of your script.
|
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
|
that, lacking zero, they had no way to indicate successful termination
|
||||||
of their C programs.\"** *-- Robert Firth*
|
of their C programs."** *-- Robert Firth*
|
||||||
|
|
||||||
## Misc
|
## Misc
|
||||||
|
|
||||||
@ -405,5 +403,5 @@ of their C programs.\"** *-- Robert Firth*
|
|||||||
### Tooling
|
### Tooling
|
||||||
|
|
||||||
- some of these guidelines, such as indentation, positioning of
|
- 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)
|
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
|
won't display the character-sequence, but will perform some action. You
|
||||||
can print the codes with a simple `echo` command.
|
can print the codes with a simple `echo` command.
|
||||||
|
|
||||||
[**Note:**]{.underline} I see codes referenced as \"Bash colors\"
|
<u>**Note:**</u> I see codes referenced as "Bash colors"
|
||||||
sometimes (several \"Bash tutorials\" etc\...): That's a completely
|
sometimes (several "Bash tutorials" etc...): That's a completely
|
||||||
incorrect definition.
|
incorrect definition.
|
||||||
|
|
||||||
## The tput command
|
## The tput command
|
||||||
@ -43,7 +43,7 @@ understands).
|
|||||||
|
|
||||||
## The codes
|
## 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
|
actions - take it as quick reference. The documentation of your terminal
|
||||||
or the `terminfo` database is always the preferred source when something
|
or the `terminfo` database is always the preferred source when something
|
||||||
is unclear! Also the `tput` acronyms are usually the ones dedicated for
|
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
|
understands many more! But let's keep the discussion centered on common
|
||||||
shell scripting ;-)
|
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.
|
code. Feel free to mail me or fix it.
|
||||||
|
|
||||||
The ANSI codes always start with the ESC character. (ASCII 0x1B or octal
|
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
|
All codes that can be used with `tput` can be found in terminfo(5). (on
|
||||||
OpenBSD at least) See [OpenBSD's
|
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)
|
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.
|
to use with tput. A description of each code is also provided.
|
||||||
|
|
||||||
### General useful ASCII codes
|
### General useful ASCII codes
|
||||||
|
|
||||||
The **Ctrl-Key** representation is simply associating the non-printable
|
The **Ctrl-Key** representation is simply associating the non-printable
|
||||||
characters from ASCII code 1 with the printable (letter) characters from
|
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
|
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
|
(and input method) and historically comes from one of the VT series of
|
||||||
terminals.
|
terminals.
|
||||||
|
|
||||||
Name decimal octal hex C-escape Ctrl-Key Description
|
|Name|decimal|octal|hex|C-escape|Ctrl-Key|Description|
|
||||||
------- --------- ------- ------ ---------- ---------- --------------------------------
|
|-------|---------|-------|------|----------|----------|--------------------------------|
|
||||||
`BEL` 7 007 0x07 `\a` `^G` Terminal bell
|
|`BEL`|7|007|0x07|`\a`|`^G`|Terminal bell|
|
||||||
`BS` 8 010 0x08 `\b` `^H` Backspace
|
|`BS`|8|010|0x08|`\b`|`^H`|Backspace|
|
||||||
`HT` 9 011 0x09 `\t` `^I` Horizontal TAB
|
|`HT`|9|011|0x09|`\t`|`^I`|Horizontal TAB|
|
||||||
`LF` 10 012 0x0A `\n` `^J` Linefeed (newline)
|
|`LF`|10|012|0x0A|`\n`|`^J`|Linefeed (newline)|
|
||||||
`VT` 11 013 0x0B `\v` `^K` Vertical TAB
|
|`VT`|11|013|0x0B|`\v`|`^K`|Vertical TAB|
|
||||||
`FF` 12 014 0x0C `\f` `^L` Formfeed (also: New page `NP`)
|
|`FF`|12|014|0x0C|`\f`|`^L`|Formfeed (also: New page `NP`)|
|
||||||
`CR` 13 015 0x0D `\r` `^M` Carriage return
|
|`CR`|13|015|0x0D|`\r`|`^M`|Carriage return|
|
||||||
`ESC` 27 033 0x1B `<none>` `^[` Escape character
|
|`ESC`|27|033|0x1B|`<none>`|`^[`|Escape character|
|
||||||
`DEL` 127 177 0x7F `<none>` `<none>` Delete character
|
|`DEL`|127|177|0x7F|`<none>`|`<none>`|Delete character|
|
||||||
|
|
||||||
### Cursor handling
|
### Cursor handling
|
||||||
|
|
||||||
@ -123,44 +123,43 @@ terminals.
|
|||||||
|
|
||||||
### General text attributes
|
### General text attributes
|
||||||
|
|
||||||
ANSI terminfo equivalent Description
|
|ANSI|terminfo equivalent|Description|
|
||||||
--------- ----------------------------- ------------------------------------------------
|
|----|-------------------|-----------|
|
||||||
`[ 0 m` `sgr0` Reset all attributes
|
|`[ 0 m`|`sgr0`|Reset all attributes|
|
||||||
`[ 1 m` `bold` Set \"bright\" attribute
|
|`[ 1 m`|`bold`|Set "bright" attribute|
|
||||||
`[ 2 m` `dim` Set \"dim\" attribute
|
|`[ 2 m`|`dim`|Set "dim" attribute|
|
||||||
`[ 3 m` `smso` Set \"standout\" attribute
|
|`[ 3 m`|`smso`|Set "standout" attribute|
|
||||||
`[ 4 m` set `smul` unset `rmul` :?: Set \"underscore\" (underlined text) attribute
|
|`[ 4 m`|set `smul` unset `rmul` :?:|Set "underscore" (underlined text) attribute|
|
||||||
`[ 5 m` `blink` Set \"blink\" attribute
|
|`[ 5 m`|`blink`|Set "blink" attribute|
|
||||||
`[ 7 m` `rev` Set \"reverse\" attribute
|
|`[ 7 m`|`rev`|Set "reverse" attribute|
|
||||||
`[ 8 m` `invis` Set \"hidden\" attribute
|
|`[ 8 m`|`invis`|Set "hidden" attribute|
|
||||||
|
|
||||||
### Foreground coloring
|
### Foreground coloring
|
||||||
|
|
||||||
ANSI terminfo equivalent Description
|
|ANSI|terminfo equivalent|Description|
|
||||||
----------- --------------------- ----------------------------------------------
|
|----|-------------------|-----------|
|
||||||
`[ 3 0 m` `setaf 0` Set **foreground** to color #0 - **black**
|
|`[ 3 0 m`|`setaf 0`|Set **foreground** to color \#0 - **black**|
|
||||||
`[ 3 1 m` `setaf 1` Set **foreground** to color #1 - **red**
|
|`[ 3 1 m`|`setaf 1`|Set **foreground** to color \#1 - **red**|
|
||||||
`[ 3 2 m` `setaf 2` Set **foreground** to color #2 - **green**
|
|`[ 3 2 m`|`setaf 2`|Set **foreground** to color \#2 - **green**|
|
||||||
`[ 3 3 m` `setaf 3` Set **foreground** to color #3 - **yellow**
|
|`[ 3 3 m`|`setaf 3`|Set **foreground** to color \#3 - **yellow**|
|
||||||
`[ 3 4 m` `setaf 4` Set **foreground** to color #4 - **blue**
|
|`[ 3 4 m`|`setaf 4`|Set **foreground** to color \#4 - **blue**|
|
||||||
`[ 3 5 m` `setaf 5` Set **foreground** to color #5 - **magenta**
|
|`[ 3 5 m`|`setaf 5`|Set **foreground** to color \#5 - **magenta**|
|
||||||
`[ 3 6 m` `setaf 6` Set **foreground** to color #6 - **cyan**
|
|`[ 3 6 m`|`setaf 6`|Set **foreground** to color \#6 - **cyan**|
|
||||||
`[ 3 7 m` `setaf 7` Set **foreground** to color #7 - **white**
|
|`[ 3 7 m`|`setaf 7`|Set **foreground** to color \#7 - **white**|
|
||||||
`[ 3 9 m` `setaf 9` Set **default** color as foreground color
|
|`[ 3 9 m`|`setaf 9`|Set **default** color as foreground color|
|
||||||
|
|
||||||
### Background coloring
|
### Background coloring
|
||||||
|
|
||||||
ANSI terminfo equivalent Description
|
|ANSI|terminfo equivalent|Description|
|
||||||
----------- --------------------- ----------------------------------------------
|
|----|-------------------|-----------|
|
||||||
`[ 4 0 m` `setab 0` Set **background** to color #0 - **black**
|
|`[ 4 0 m`|`setab 0`|Set **background** to color \#0 - **black**|
|
||||||
`[ 4 1 m` `setab 1` Set **background** to color #1 - **red**
|
|`[ 4 1 m`|`setab 1`|Set **background** to color \#1 - **red**|
|
||||||
`[ 4 2 m` `setab 2` Set **background** to color #2 - **green**
|
|`[ 4 2 m`|`setab 2`|Set **background** to color \#2 - **green**|
|
||||||
`[ 4 3 m` `setab 3` Set **background** to color #3 - **yellow**
|
|`[ 4 3 m`|`setab 3`|Set **background** to color \#3 - **yellow**|
|
||||||
`[ 4 4 m` `setab 4` Set **background** to color #4 - **blue**
|
|`[ 4 4 m`|`setab 4`|Set **background** to color \#4 - **blue**|
|
||||||
`[ 4 5 m` `setab 5` Set **background** to color #5 - **magenta**
|
|`[ 4 5 m`|`setab 5`|Set **background** to color \#5 - **magenta**|
|
||||||
`[ 4 6 m` `setab 6` Set **background** to color #6 - **cyan**
|
|`[ 4 6 m`|`setab 6`|Set **background** to color \#6 - **cyan**|
|
||||||
`[ 4 7 m` `setab 7` Set **background** to color #7 - **white**
|
|`[ 4 7 m`|`setab 7`|Set **background** to color \#7 - **white**|
|
||||||
`[ 4 9 m` `setab 9` Set **default** color as background color
|
|`[ 4 9 m`|`setab 9`|Set **default** color as background color|
|
||||||
|
|
||||||
### Misc codes
|
### Misc codes
|
||||||
|
|
||||||
@ -168,7 +167,7 @@ terminals.
|
|||||||
|
|
||||||
Used capabilities: `smcup`, `rmcup`
|
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
|
terminal contents after they do their work (like `vim`). This can be
|
||||||
done by the following commands:
|
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`,
|
termcap/terminfo. While `xterm` and most of its clones (`rxvt`, `urxvt`,
|
||||||
etc) will support the instructions, your operating system may not
|
etc) will support the instructions, your operating system may not
|
||||||
include references to them in its default xterm profile. (FreeBSD, in
|
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
|
nothing for you, and you don't want to modify your system
|
||||||
termcap/terminfo data, and you KNOW that you are using a compatible
|
termcap/terminfo data, and you KNOW that you are using a compatible
|
||||||
xterm application, the following may work for you:
|
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
|
Certain software uses these codes (via their termcap capabilities) as
|
||||||
well. You may have seen the screen save/restore in `less`, `vim`, `top`,
|
well. You may have seen the screen save/restore in `less`, `vim`, `top`,
|
||||||
`screen` and others. Some of these applications may also provide
|
`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
|
has a `-X` option for this, which can also be set in an environment
|
||||||
variable:
|
variable:
|
||||||
|
|
||||||
export LESS=X
|
export LESS=X
|
||||||
less /path/to/file
|
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`:
|
adding the following to your `~/.vimrc`:
|
||||||
|
|
||||||
set t_ti= t_te=
|
set t_ti= t_te=
|
||||||
@ -226,7 +225,7 @@ in graphical environments.
|
|||||||
|
|
||||||
The Virtual Terminal implemented in the Linux kernel supports only 16
|
The Virtual Terminal implemented in the Linux kernel supports only 16
|
||||||
colors, and the usual default terminfo entry for `TERM=linux` defines
|
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.
|
switch to, to get the other 8 colors.
|
||||||
|
|
||||||
## Bash examples
|
## Bash examples
|
||||||
@ -237,11 +236,11 @@ switch to, to get the other 8 colors.
|
|||||||
|
|
||||||
### Colors using tput
|
### 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."
|
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_NORM="$(tput setaf 9)"
|
||||||
COL_RED="$(tput setaf 1)"
|
COL_RED="$(tput setaf 1)"
|
||||||
@ -250,7 +249,7 @@ switch to, to get the other 8 colors.
|
|||||||
|
|
||||||
### Misc
|
### Misc
|
||||||
|
|
||||||
[HOME function]{.underline}
|
<u>HOME function</u>
|
||||||
|
|
||||||
home() {
|
home() {
|
||||||
# yes, actually not much shorter ;-)
|
# 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
|
different \"names\" (hostname, FQDN, IP) and redirects the output to the
|
||||||
`known_hosts`-file.
|
`known_hosts`-file.
|
||||||
|
|
||||||
[**Notes:**]{.underline}
|
<u>**Notes:**</u>
|
||||||
|
|
||||||
- if done blindly, the `known_host`-file may grow very large. It might
|
- if done blindly, the `known_host`-file may grow very large. It might
|
||||||
be wise to check for key existance first
|
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
|
you need correct escapes or quotes to not generate shell special
|
||||||
characters out of normal text (like embedded dollar signs `$`).
|
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
|
A loop over the own arguments that writes out properly quoted/escaped
|
||||||
code to the generated script file
|
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
|
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 can range from 2 to 64. To represent digits in a
|
||||||
specified base greater than 10, characters other than 0 to 9 are needed
|
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`
|
- `0 ... 9`
|
||||||
- `a ... z`
|
- `a ... z`
|
||||||
@ -124,8 +124,8 @@ named parameters, e.g.:
|
|||||||
# will output "3"!
|
# will output "3"!
|
||||||
|
|
||||||
Of course, in the end, when it finally evaluates to something that is
|
Of course, in the end, when it finally evaluates to something that is
|
||||||
**not** a valid arithmetic expression (newlines, ordinary text, \...)
|
**not** a valid arithmetic expression (newlines, ordinary text, ...)
|
||||||
then you\'ll get an error.
|
then you'll get an error.
|
||||||
|
|
||||||
When variables are referenced, the notation `1 + $X` is equivalent to
|
When variables are referenced, the notation `1 + $X` is equivalent to
|
||||||
the notation `1 + X`, both are allowed.
|
the notation `1 + X`, both are allowed.
|
||||||
@ -138,10 +138,10 @@ an arithmetic expression.
|
|||||||
## Truth
|
## Truth
|
||||||
|
|
||||||
Unlike command exit and return codes, arithmetic expressions evaluate to
|
Unlike command exit and return codes, arithmetic expressions evaluate to
|
||||||
logical \"true\" when they are not 0. When they are 0, they evaluate to
|
logical "true" when they are not 0. When they are 0, they evaluate to
|
||||||
\"false\". The [arithmetic evaluation compound
|
"false". The [arithmetic evaluation compound
|
||||||
command](../syntax/ccmd/arithmetic_eval.md) reverses the \"truth\" of an
|
command](../syntax/ccmd/arithmetic_eval.md) reverses the "truth" of an
|
||||||
arithmetic expression to match the \"truth\" of command exit codes:
|
arithmetic expression to match the "truth" of command exit codes:
|
||||||
|
|
||||||
- if the arithmetic expression brings up a value not 0 (arithmetic
|
- if the arithmetic expression brings up a value not 0 (arithmetic
|
||||||
true), it returns 0 (shell true)
|
true), it returns 0 (shell true)
|
||||||
@ -160,89 +160,79 @@ That means, the following `if`-clause will execute the `else`-thread:
|
|||||||
|
|
||||||
### Assignment
|
### Assignment
|
||||||
|
|
||||||
Operator Description
|
|Operator|Description|
|
||||||
--------------------- ----------------------------------------------------------------------------------------------------
|
|--------|-----------|
|
||||||
`<ID> = <EXPR>` normal assignment
|
|`<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> %= <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> >>= <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)
|
|`<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
|
### Calculations
|
||||||
|
|
||||||
Operator Description
|
|Operator|Description|
|
||||||
---------- --------------------
|
|--------|-----------|
|
||||||
`*` multiplication
|
|`*`|multiplication|
|
||||||
`/` division
|
|`/`|division|
|
||||||
`%` remainder (modulo)
|
|`%`|remainder (modulo)|
|
||||||
`+` addition
|
|`+`|addition|
|
||||||
`-` subtraction
|
|`-`|subtraction|
|
||||||
`**` exponentiation
|
|`**`|exponentiation|
|
||||||
|
|
||||||
### Comparisons
|
### Comparisons
|
||||||
|
|
||||||
Operator Description
|
|Operator|Description|
|
||||||
---------- -----------------------------------
|
|--------|-----------|
|
||||||
`<` comparison: less than
|
|`<`|comparison: less than|
|
||||||
`>` comparison: greater than
|
|`>`|comparison: greater than|
|
||||||
`<=` comparison: less than or equal
|
|`<=`|comparison: less than or equal|
|
||||||
`>=` comparison: greater than or equal
|
|`>=`|comparison: greater than or equal|
|
||||||
`==` equality
|
|`==`|equality|
|
||||||
`!=` inequality
|
|`!=`|inequality|
|
||||||
|
|
||||||
### Bit operations
|
### Bit operations
|
||||||
|
|
||||||
Operator Description
|
|Operator|Description|
|
||||||
---------- ----------------------------
|
|--------|-----------|
|
||||||
`~` bitwise negation
|
|`~`|bitwise negation|
|
||||||
`<<` bitwise shifting (left)
|
|`<<`|bitwise shifting (left)|
|
||||||
`>>` bitwise shifting (right)
|
|`>>`|bitwise shifting (right)|
|
||||||
`&` bitwise AND
|
|`&`|bitwise AND|
|
||||||
`^` bitwise exclusive OR (XOR)
|
|`^`|bitwise exclusive OR (XOR)|
|
||||||
`|` bitwise OR
|
|`|`|bitwise OR|
|
||||||
|
|
||||||
### Logical
|
### Logical
|
||||||
|
|
||||||
Operator Description
|
|Operator|Description|
|
||||||
---------- ------------------
|
|--------|-----------|
|
||||||
`!` logical negation
|
|`!`|logical negation|
|
||||||
`&&` logical AND
|
|`&&`|logical AND|
|
||||||
`||` logical OR
|
|`||`|logical OR|
|
||||||
|
|
||||||
|
|
||||||
### Misc
|
### Misc
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------
|
|Operator|Description|
|
||||||
Operator Description
|
|--------|-----------|
|
||||||
---------------------------- --------------------------------------------------------------------
|
|`id++`|**post-increment** of the variable `id` (not required by POSIX(r))|
|
||||||
`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--` **post-decrement** of the variable `id` (not required by POSIX(r))
|
|`--id`|**pre-decrement** of the variable `id` (not required by POSIX(r))|
|
||||||
|
|`+`|unary plus|
|
||||||
`++id` **pre-increment** of the variable `id` (not required by POSIX(r))
|
|`-`|unary minus|
|
||||||
|
|`<EXPR> ? <EXPR> : <EXPR>`|conditional (ternary) operator <condition> ? <result-if-true> : <result-if-false>|
|
||||||
`--id` **pre-decrement** of the variable `id` (not required by POSIX(r))
|
|`<EXPR> , <EXPR>`|expression list|
|
||||||
|
|`( <EXPR> )`|subexpression (to force precedence)|
|
||||||
`+` 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
|
## Precedence
|
||||||
|
|
||||||
The operator precedence is as follows (highest -> lowest):
|
The operator precedence is as follows (highest -> lowest):
|
||||||
|
|
||||||
- Postfix (`id++`, `id--`)
|
- Postfix (`id++`, `id--`)
|
||||||
- Prefix (`++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`
|
codes of commands or functions to be executed. `if` statements, `while`
|
||||||
loops, etc., they all take the return codes of commands as conditions.
|
loops, etc., they all take the return codes of commands as conditions.
|
||||||
|
|
||||||
Now the problem is: The return codes (0 means \"TRUE\" or \"SUCCESS\",
|
Now the problem is: The return codes (0 means "TRUE" or "SUCCESS",
|
||||||
not 0 means \"FALSE\" or \"FAILURE\") don't correspond to the meaning
|
not 0 means "FALSE" or "FAILURE") don't correspond to the meaning
|
||||||
of the result of an arithmetic expression (0 means \"FALSE\", not 0
|
of the result of an arithmetic expression (0 means "FALSE", not 0
|
||||||
means \"TRUE\").
|
means "TRUE").
|
||||||
|
|
||||||
That's why all commands and keywords that do arithmetic operations
|
That's why all commands and keywords that do arithmetic operations
|
||||||
attempt to **translate** the arithmetical meaning into an equivalent
|
attempt to **translate** the arithmetical meaning into an equivalent
|
||||||
return code. This simply means:
|
return code. This simply means:
|
||||||
|
|
||||||
- if the arithmetic operation evaluates to 0 (\"FALSE\"), the return
|
- if the arithmetic operation evaluates to 0 ("FALSE"), the return
|
||||||
code is not 0 (\"FAILURE\")
|
code is not 0 ("FAILURE")
|
||||||
- if the arithmetic operation evaluates to 1 (\"TRUE\"), the return
|
- if the arithmetic operation evaluates to 1 ("TRUE"), the return
|
||||||
code is 0 (\"SUCCESS\")
|
code is 0 ("SUCCESS")
|
||||||
|
|
||||||
This way, you can easily use arithmetic expressions (along with the
|
This way, you can easily use arithmetic expressions (along with the
|
||||||
commands or keywords that operate them) as conditions for `if`, `while`
|
commands or keywords that operate them) as conditions for `if`, `while`
|
||||||
@ -302,47 +292,48 @@ else
|
|||||||
fi
|
fi
|
||||||
```
|
```
|
||||||
|
|
||||||
<WRAP center round important> Beware that `set -e` can change the
|
!!! warning "Beware that `set -e` can change the runtime behavior of scripts."
|
||||||
runtime behavior of scripts. For example,
|
|
||||||
|
|
||||||
This non-equivalence of code behavior deserves some attention. Consider
|
For example,
|
||||||
what happens if v happens to be zero in the expression below:
|
|
||||||
|
|
||||||
``` bash
|
This non-equivalence of code behavior deserves some attention. Consider
|
||||||
((v += 0))
|
what happens if v happens to be zero in the expression below:
|
||||||
echo $?
|
|
||||||
```
|
|
||||||
|
|
||||||
1
|
``` bash
|
||||||
|
((v += 0))
|
||||||
|
echo $?
|
||||||
|
```
|
||||||
|
|
||||||
(\"FAILURE\")
|
1
|
||||||
|
|
||||||
``` bash
|
("FAILURE")
|
||||||
v=$((v + 0))
|
|
||||||
echo $?
|
|
||||||
```
|
|
||||||
|
|
||||||
0
|
``` bash
|
||||||
|
v=$((v + 0))
|
||||||
|
echo $?
|
||||||
|
```
|
||||||
|
|
||||||
(\"SUCCESS\")
|
0
|
||||||
|
|
||||||
The return code behavior is not equivalent to the arithmetic behavior,
|
("SUCCESS")
|
||||||
as has been noted.
|
|
||||||
|
|
||||||
A workaround is to use a list operation that returns True, or use the
|
The return code behavior is not equivalent to the arithmetic behavior,
|
||||||
second assignment style.
|
as has been noted.
|
||||||
|
|
||||||
``` bash
|
A workaround is to use a list operation that returns True, or use the
|
||||||
((v += 0)) || :
|
second assignment style.
|
||||||
echo $?
|
|
||||||
```
|
|
||||||
|
|
||||||
0
|
``` bash
|
||||||
|
((v += 0)) || :
|
||||||
|
echo $?
|
||||||
|
```
|
||||||
|
|
||||||
(\"SUCCESS\")
|
0
|
||||||
|
|
||||||
This change in code behavior was discovered once the script was run
|
("SUCCESS")
|
||||||
under set -e. </WRAP>
|
|
||||||
|
This change in code behavior was discovered once the script was run
|
||||||
|
under set -e.
|
||||||
|
|
||||||
## Arithmetic expressions in Bash
|
## Arithmetic expressions in Bash
|
||||||
|
|
||||||
@ -350,4 +341,4 @@ under set -e. </WRAP>
|
|||||||
- [Arithmetic expansion](../syntax/expansion/arith.md)
|
- [Arithmetic expansion](../syntax/expansion/arith.md)
|
||||||
- [Arithmetic evaluation compound
|
- [Arithmetic evaluation compound
|
||||||
command](../syntax/ccmd/arithmetic_eval.md)
|
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
|
ksh88. Similar, partially compatible syntax was inherited by many
|
||||||
derivatives including Bash. Indexed arrays always carry the `-a`
|
derivatives including Bash. Indexed arrays always carry the `-a`
|
||||||
attribute.
|
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
|
arbitrary nonempty strings as keys. In other words, associative
|
||||||
arrays allow you to look up a value from a table based upon its
|
arrays allow you to look up a value from a table based upon its
|
||||||
corresponding string label. **Associative arrays are always
|
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
|
The following explicitly give variables array attributes, making them
|
||||||
arrays:
|
arrays:
|
||||||
|
|
||||||
Syntax Description
|
|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=()`|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.
|
|`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 **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.
|
|`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
|
As an example, and for use below, let's declare our `NAMES` array as
|
||||||
described [above](#purpose):
|
described [above](#purpose):
|
||||||
@ -116,31 +116,32 @@ described [above](#purpose):
|
|||||||
Storing values in arrays is quite as simple as storing values in normal
|
Storing values in arrays is quite as simple as storing values in normal
|
||||||
variables.
|
variables.
|
||||||
|
|
||||||
Syntax Description
|
|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[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[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=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=(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=([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=([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+=(E1\ E2\ ...)`|Append to ARRAY.|
|
||||||
`ARRAY=("${ANOTHER_ARRAY[@]}")` Copy ANOTHER_ARRAY to ARRAY, copying each element.
|
|`ARRAY=("${ANOTHER_ARRAY[@]}")`|Copy ANOTHER_ARRAY to ARRAY, copying each element.|
|
||||||
|
|
||||||
As of now, arrays can't be exported.
|
As of now, arrays can't be exported.
|
||||||
|
|
||||||
### Getting values
|
### Getting values
|
||||||
|
|
||||||
<note> For completeness and details on several parameter expansion
|
!!! info ""
|
||||||
variants, see the [article about parameter expansion](../syntax/pe.md) and
|
For completeness and details on several parameter expansion
|
||||||
check the notes about arrays. </note>
|
variants, see the [article about parameter expansion](../syntax/pe.md) and
|
||||||
|
check the notes about arrays.
|
||||||
|
|
||||||
Syntax Description
|
|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[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[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[@]}" ${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.
|
|`"${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
|
For clarification: When you use the subscripts `@` or `*` for
|
||||||
mass-expanding, then the behaviour is exactly what it is for `$@` and
|
mass-expanding, then the behaviour is exactly what it is for `$@` and
|
||||||
@ -150,62 +151,50 @@ article to understand what's going on.
|
|||||||
|
|
||||||
### Metadata
|
### Metadata
|
||||||
|
|
||||||
--------------------------------------------------------------------------------------------------------------------------------
|
|Syntax|Description|
|
||||||
Syntax Description
|
|------|-----------|
|
||||||
--------------------- ----------------------------------------------------------------------------------------------------------
|
|`${#ARRAY[N]}`|Expands to the **length** of an individual array member at index `N` (**stringlength**)|
|
||||||
`${#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[STRING]}` Expands to the **length** of an individual associative array member at index `STRING` (**stringlength**)
|
|`${!ARRAY[@]}` \ `${!ARRAY[*]}`|Expands to the **indexes** in `ARRAY` since BASH 3.0|
|
||||||
|
|
||||||
`${#ARRAY[@]}`\ Expands to the **number of elements** in `ARRAY`
|
|
||||||
`${#ARRAY[*]}`
|
|
||||||
|
|
||||||
`${!ARRAY[@]}`\ Expands to the **indexes** in `ARRAY` since BASH 3.0
|
|
||||||
`${!ARRAY[*]}`
|
|
||||||
--------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
### Destruction
|
### Destruction
|
||||||
|
|
||||||
The [unset](../commands/builtin/unset.md) builtin command is used to destroy
|
The [unset](../commands/builtin/unset.md) builtin command is used to destroy
|
||||||
(unset) arrays or individual elements of arrays.
|
(unset) arrays or individual elements of arrays.
|
||||||
|
|
||||||
--------------------------------------------------------------------------------------------------
|
|Syntax|Description|
|
||||||
Syntax Description
|
|------|-----------|
|
||||||
-------------------------- -----------------------------------------------------------------------
|
|`unset -v ARRAY` \ `unset -v ARRAY[@]` \ `unset -v ARRAY[*]`|Destroys a complete array|
|
||||||
`unset -v ARRAY`\ Destroys a complete array
|
|`unset -v ARRAY[N]`|Destroys the array element at index `N`|
|
||||||
`unset -v ARRAY[@]`\
|
|`unset -v ARRAY[STRING]`|Destroys the array element of the associative array at index `STRING`|
|
||||||
`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`
|
|
||||||
--------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
It is best to [explicitly specify
|
It is best to [explicitly specify
|
||||||
-v](../commands/builtin/unset.md#portability_considerations) when unsetting
|
-v](../commands/builtin/unset.md#portability_considerations) when unsetting
|
||||||
variables with unset.
|
variables with unset.
|
||||||
|
|
||||||
<note warning> Specifying unquoted array elements as arguments to any
|
!!! warning "warning"
|
||||||
command, such as with the syntax above **may cause [pathname
|
Specifying unquoted array elements as arguments to any
|
||||||
expansion](../syntax/expansion/globs.md) to occur** due to the presence of
|
command, such as with the syntax above **may cause [pathname
|
||||||
glob characters.
|
expansion](../syntax/expansion/globs.md) to occur** due to the presence of
|
||||||
|
glob characters.
|
||||||
|
|
||||||
Example: You are in a directory with a file named `x1`, and you want to
|
Example: You are in a directory with a file named `x1`, and you want to
|
||||||
destroy an array element `x[1]`, with
|
destroy an array element `x[1]`, with
|
||||||
|
|
||||||
unset x[1]
|
unset x[1]
|
||||||
|
|
||||||
then pathname expansion will expand to the filename `x1` and break your
|
then pathname expansion will expand to the filename `x1` and break your
|
||||||
processing!
|
processing!
|
||||||
|
|
||||||
Even worse, if `nullglob` is set, your array/index will disappear.
|
Even worse, if `nullglob` is set, your array/index will disappear.
|
||||||
|
|
||||||
To avoid this, **always quote** the array name and index:
|
To avoid this, **always quote** the array name and index:
|
||||||
|
|
||||||
unset -v 'x[1]'
|
unset -v 'x[1]'
|
||||||
|
|
||||||
This applies generally to all commands which take variable names as
|
This applies generally to all commands which take variable names as
|
||||||
arguments. Single quotes preferred. </note>
|
arguments. Single quotes preferred.
|
||||||
|
|
||||||
## Usage
|
## 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.
|
elements, only works for arrays where all elements are set, of course.
|
||||||
If one element in the middle is removed, then the calculation is
|
If one element in the middle is removed, then the calculation is
|
||||||
nonsense, because the number of elements doesn't correspond to the
|
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
|
Now, suppose that you want to replace your array `sentence` with the
|
||||||
values in the [previously-declared array](#purpose) `NAMES` . You might
|
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[End]='in what you send'
|
||||||
sentence['Very end']=...
|
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:
|
ordered in memory like they were declared, it could look like this:
|
||||||
|
|
||||||
# output from 'set' command
|
# 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
|
evaluating the arithmetic. A special-case of this is shown in the next
|
||||||
section.
|
section.
|
||||||
|
|
||||||
<note> Bash declaration commands are really keywords in disguise. They
|
!!! info "info"
|
||||||
magically parse arguments to determine whether they are in the form of a
|
Bash declaration commands are really keywords in disguise. They
|
||||||
valid assignment. If so, they are evaluated as assignments. If not, they
|
magically parse arguments to determine whether they are in the form of a
|
||||||
are undergo normal argument expansion before being passed to the builtin
|
valid assignment. If so, they are evaluated as assignments. If not, they
|
||||||
which evaluates the resulting string as an assignment (somewhat like
|
are undergo normal argument expansion before being passed to the builtin
|
||||||
`eval`, but there are differences.) `'Todo:`\' Discuss this in detail.
|
which evaluates the resulting string as an assignment (somewhat like
|
||||||
</note>
|
`eval`, but there are differences.) `'Todo:`\' Discuss this in detail.
|
||||||
|
|
||||||
### Indirection
|
### 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
|
results. This is mainly useful for passing arrays (especially multiple
|
||||||
arrays) by name to a function.
|
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
|
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
|
correspond to a key-value of the array given as the second argument. It
|
||||||
demonstrates both indirect array expansion and indirect key-passing
|
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
|
the subscript or the value first can change in almost every shell
|
||||||
for both expansions and arithmetic variables. See [evaluation
|
for both expansions and arithmetic variables. See [evaluation
|
||||||
order](#evaluation_order) for details.
|
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
|
array indexes relative to the highest-numbered index. You must use
|
||||||
the subscript expansion, i.e. `"${arr[@]:(-n):1}"`, to expand the
|
the subscript expansion, i.e. `"${arr[@]:(-n):1}"`, to expand the
|
||||||
nth-last element (or the next-highest indexed after `n` if `arr[n]`
|
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
|
### 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
|
compound assignment, including the subscript for globbing. The
|
||||||
subscript part is considered quoted, but any unquoted glob
|
subscript part is considered quoted, but any unquoted glob
|
||||||
characters on the right-hand side of the `[...]=` will be clumped
|
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
|
1=a
|
||||||
`
|
`
|
||||||
- **Fixed in 4.3** In addition to the above globbing issue,
|
- **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} )
|
and pathname expansion. `$ set -x; foo=bar declare arr=( {1..10} )
|
||||||
+ foo=bar
|
+ foo=bar
|
||||||
+ declare 'arr=(1)' 'arr=(2)' 'arr=(3)' 'arr=(4)' 'arr=(5)' 'arr=(6)' 'arr=(7)' 'arr=(8)' 'arr=(9)' 'arr=(10)'
|
+ 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.
|
detailed discussion on arrays with many examples.
|
||||||
- [BashSheet - Arrays](http://mywiki.wooledge.org/BashSheet#Arrays) -
|
- [BashSheet - Arrays](http://mywiki.wooledge.org/BashSheet#Arrays) -
|
||||||
Bashsheet quick-reference on Greycat's wiki.
|
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
|
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.
|
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.
|
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
|
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
|
ls -l
|
||||||
LC_ALL=C ls
|
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
|
to the environment of the `ls` program. It doesn't affect your current
|
||||||
shell. This also works while calling functions, unless Bash runs in
|
shell. This also works while calling functions, unless Bash runs in
|
||||||
POSIX(r) mode (in which case it affects your current shell).
|
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
|
means success, and the rest mean either something failed, or there is an
|
||||||
issue to report back to the calling program.
|
issue to report back to the calling program.
|
||||||
|
|
||||||
<wrap center round info 90%> The simple command construct is the
|
!!! info "info"
|
||||||
**base** for all higher constructs. Everything you execute, from
|
The simple command construct is the
|
||||||
pipelines to functions, finally ends up in (many) simple commands.
|
**base** for all higher constructs. Everything you execute, from
|
||||||
That's why Bash only has one method to [expand and execute a simple
|
pipelines to functions, finally ends up in (many) simple commands.
|
||||||
command](../syntax/grammar/parser_exec.md). </wrap>
|
That's why Bash only has one method to [expand and execute a simple
|
||||||
|
command](../syntax/grammar/parser_exec.md).
|
||||||
|
|
||||||
## Pipelines
|
## Pipelines
|
||||||
|
|
||||||
FIXME Missing an additional article about pipelines and pipelining
|
!!! warning "FIXME"
|
||||||
|
Missing an additional article about pipelines and pipelining
|
||||||
|
|
||||||
`[time [-p]] [ ! ] command [ | command2 ... ]`
|
`[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
|
name for a construct. Such a pipeline isn't necessarily a pair of
|
||||||
commands where stdout/stdin is connected via a real pipe.
|
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.
|
directory entries in /etc.
|
||||||
|
|
||||||
The last command in the pipeline will set the exit code for the
|
The last command in the pipeline will set the exit code for the
|
||||||
pipeline. This exit code can be \"inverted\" by prefixing an exclamation
|
pipeline. This exit code can be "inverted" by prefixing an exclamation
|
||||||
mark to the pipeline: An unsuccessful pipeline will exit \"successful\"
|
mark to the pipeline: An unsuccessful pipeline will exit "successful"
|
||||||
and vice versa. In this example, the commands in the if stanza will be
|
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
|
if ! grep '^root:' /etc/passwd; then
|
||||||
echo "No root user defined... eh?"
|
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
|
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
|
**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),
|
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
|
acts on) exit code 0 (TRUE) and the `then` part of the `if` stanza is
|
||||||
executed. One could say we checked for
|
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 [set option pipefail](../commands/builtin/set.md#attributes) determines
|
||||||
the behavior of how bash reports the exit code of a pipeline. If it's
|
the behavior of how bash reports the exit code of a pipeline. If it's
|
||||||
@ -117,7 +119,8 @@ syntax:
|
|||||||
|
|
||||||
## Lists
|
## 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)
|
A list is a sequence of one or more [pipelines](#pipelines)
|
||||||
separated by one of the operators `;`, `&`, `&&`, or `││`, and
|
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!
|
Your whole Bash script technically is one big single list!
|
||||||
|
|
||||||
Operator Description
|
|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> <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
|
|`<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
|
|`<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 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)
|
|`<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
|
## Compound Commands
|
||||||
|
|
||||||
@ -144,7 +147,7 @@ See also the [list of compound commands](../syntax/ccmd/intro.md).
|
|||||||
|
|
||||||
There are two forms of compound commands:
|
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
|
- completly independant syntax elements
|
||||||
|
|
||||||
Essentially, everything else that's not described in this article.
|
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
|
See the following table for a short overview (no details - just an
|
||||||
overview):
|
overview):
|
||||||
|
|
||||||
Compound command syntax Description
|
|Compound command syntax|Description|
|
||||||
------------------------------------------------------------ ---------------------------------------------------------------------------------------------------------------------------------------------------------
|
|-----------------------|-----------|
|
||||||
`( <LIST> )` Execute `<LIST>` in an extra subshell => [article](../syntax/ccmd/grouping_subshell.md)
|
|`( <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)
|
|`{ <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 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)
|
|`[[ <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 <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)
|
|`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)
|
|`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)
|
|`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)
|
|`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)
|
|`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)
|
|`until <LIST1> ; do <LIST2> ; done`|Execute `<LIST2>` until `<LIST1>` returns TRUE (exit code) =\> [article](../syntax/ccmd/until_loop.md)|
|
||||||
|
|
||||||
## Shell Function Definitions
|
## 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
|
A shell function definition makes a [compound
|
||||||
command](#compound_commands) available via a new name. When
|
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.
|
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):
|
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
|
I suggest using the first form. It's specified in POSIX and all
|
||||||
Bourne-like shells seem to support it.
|
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
|
recognized the definition using curly braces (`name() { ... }`), other
|
||||||
shells allow the definition using **any** command (not just the compound
|
shells allow the definition using **any** command (not just the compound
|
||||||
command set).
|
command set).
|
||||||
@ -244,9 +248,9 @@ like this:
|
|||||||
**Just informational(1):**
|
**Just informational(1):**
|
||||||
|
|
||||||
Internally, for forking, Bash stores function definitions in environment
|
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:
|
declaring a function:
|
||||||
|
|
||||||
$ export testfn="() { echo test; }"
|
$ 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:
|
Weird function names should not be used. Quote from the maintainer:
|
||||||
|
|
||||||
- * It was a mistake to allow such characters in function names
|
- * It was a mistake to allow such characters in function names
|
||||||
(\`unset\' doesn't work to unset them without forcing -f, for
|
(`unset` doesn't work to unset them without forcing `-f`, for
|
||||||
instance). We\'re stuck with them for backwards compatibility, but I
|
instance). We're stuck with them for backwards compatibility, but I
|
||||||
don't have to encourage their use. *
|
don't have to encourage their use. *
|
||||||
|
|
||||||
## Grammar summary
|
## Grammar summary
|
||||||
@ -288,15 +292,16 @@ Weird function names should not be used. Quote from the maintainer:
|
|||||||
|
|
||||||
## Examples for classification
|
## Examples for classification
|
||||||
|
|
||||||
FIXME more\...
|
!!! warning "FIXME"
|
||||||
|
more...
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
[A (very) simple command]{.underline}
|
<u>A (very) simple command</u>
|
||||||
|
|
||||||
echo "Hello world..."
|
echo "Hello world..."
|
||||||
|
|
||||||
[All of the following are simple commands]{.underline}
|
<u>All of the following are simple commands</u>
|
||||||
|
|
||||||
x=5
|
x=5
|
||||||
|
|
||||||
@ -306,7 +311,7 @@ FIXME more\...
|
|||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
[A common compound command]{.underline}
|
<u>A common compound command</u>
|
||||||
|
|
||||||
if [ -d /data/mp3 ]; then
|
if [ -d /data/mp3 ]; then
|
||||||
cp mymusic.mp3 /data/mp3
|
cp mymusic.mp3 /data/mp3
|
||||||
|
@ -20,10 +20,10 @@
|
|||||||
|
|
||||||
The C-style for-loop is a [compound
|
The C-style for-loop is a [compound
|
||||||
command](../../syntax/basicgrammar.md#compound_commands) derived from the
|
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
|
keyword. Its purpose is to provide a convenient way to evaluate
|
||||||
arithmetic expressions in a loop, plus initialize any required
|
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.
|
mechanisms available in the language.
|
||||||
|
|
||||||
The `((;;))` syntax at the top of the loop is not an ordinary
|
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
|
### 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
|
numbers -> 101 runs!), and everytime the variable `x` is set to the
|
||||||
current value.
|
current value.
|
||||||
|
|
||||||
@ -111,9 +111,6 @@ current value.
|
|||||||
- Before every iteration it **checks** if `x ≤ 100`
|
- Before every iteration it **checks** if `x ≤ 100`
|
||||||
- After every iteration it **changes** `x++`
|
- After every iteration it **changes** `x++`
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
for ((x = 0 ; x <= 100 ; x++)); do
|
for ((x = 0 ; x <= 100 ; x++)); do
|
||||||
echo "Counter: $x"
|
echo "Counter: $x"
|
||||||
done
|
done
|
||||||
@ -131,8 +128,8 @@ will count from 0 to 100, but with a **step of 10**.
|
|||||||
### Bits analyzer
|
### Bits analyzer
|
||||||
|
|
||||||
This example loops through the bit-values of a Byte, beginning from 128,
|
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`\",
|
ending at 1. If that bit is set in the `testbyte`, it prints "`1`",
|
||||||
else \"`0`\" => it prints the binary representation of the `testbyte`
|
else "`0`" => it prints the binary representation of the `testbyte`
|
||||||
value (8 bits).
|
value (8 bits).
|
||||||
|
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
@ -161,7 +158,7 @@ value (8 bits).
|
|||||||
|
|
||||||
# vim: set fenc=utf-8 ff=unix ft=sh :
|
# vim: set fenc=utf-8 ff=unix ft=sh :
|
||||||
|
|
||||||
<div hide>
|
<div hide>
|
||||||
|
|
||||||
testbyte=123
|
testbyte=123
|
||||||
for (( n = 128 ; n >= 1 ; n /= 2 )); do
|
for (( n = 128 ; n >= 1 ; n /= 2 )); do
|
||||||
@ -173,11 +170,11 @@ value (8 bits).
|
|||||||
done
|
done
|
||||||
echo
|
echo
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
Why that one begins at 128 (highest value, on the left) and not 1
|
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
|
(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
|
We arrive at 128 for `n` through the recursive arithmetic expression
|
||||||
stored in `x`, which calculates the next-greatest power of 2 after `m`.
|
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
|
number in an arbitrary base (up to 64). Very few languages have that
|
||||||
ability built-in, even things like Python.
|
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,
|
This counts up and down from `0` to `${1:-5}`, `${2:-4}` times,
|
||||||
demonstrating more complicated arithmetic expressions with multiple
|
demonstrating more complicated arithmetic expressions with multiple
|
||||||
@ -196,7 +193,8 @@ variables.
|
|||||||
printf '%*s\n' "$((n+1))" "$n"
|
printf '%*s\n' "$((n+1))" "$n"
|
||||||
done
|
done
|
||||||
|
|
||||||
<code> \~ \$ bash <(xclip -o) 1
|
``` bash
|
||||||
|
~ \$ bash <(xclip -o) 1
|
||||||
|
|
||||||
2
|
2
|
||||||
3
|
3
|
||||||
@ -216,7 +214,8 @@ variables.
|
|||||||
3
|
3
|
||||||
2
|
2
|
||||||
|
|
||||||
1 </code>
|
1
|
||||||
|
```
|
||||||
|
|
||||||
## Portability considerations
|
## Portability considerations
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ done**, which means you can leave expansions unquoted without problems:
|
|||||||
esac
|
esac
|
||||||
|
|
||||||
This is similar to the behavior of the [conditional expression command
|
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).
|
word splitting for expansions).
|
||||||
|
|
||||||
Unlike the C-case-statement, only the matching list and nothing else is
|
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.
|
construct.
|
||||||
|
|
||||||
The `case` statement is one of the most difficult commands to indent
|
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
|
Just do your best - there are many variations of indenting style for
|
||||||
`case` and no real agreed-upon best practice.
|
`case` and no real agreed-upon best practice.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
Another one of my stupid examples\...
|
Another one of my stupid examples...
|
||||||
|
|
||||||
printf '%s ' 'Which fruit do you like most?'
|
printf '%s ' 'Which fruit do you like most?'
|
||||||
read -${BASH_VERSION+e}r fruit
|
read -${BASH_VERSION+e}r fruit
|
||||||
|
@ -23,7 +23,7 @@ alternative, historical and undocumented syntax [^1]
|
|||||||
## Description
|
## Description
|
||||||
|
|
||||||
For every word in `<WORDS>`, one iteration of the loop is performed and
|
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
|
is present to give an own word-list, then the positional parameters
|
||||||
(`"$@"`) are used (the arguments to the script or function). In this
|
(`"$@"`) are used (the arguments to the script or function). In this
|
||||||
case (and only in this case), the semicolon between the variable name
|
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
|
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.:
|
`0` (`TRUE`), if the item list `<WORDS>` evaluates to nothing (i.e.:
|
||||||
\"is empty\"!).
|
"is empty"!).
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
### Iterate over array elements
|
### Iterate over array elements
|
||||||
|
|
||||||
With some array syntax (see [arrays](../../syntax/arrays.md)) you can easily
|
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):
|
mass-expanding all elements):
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
@ -156,7 +156,7 @@ done
|
|||||||
|
|
||||||
### Loop over a number range
|
### 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
|
[brace expansion](../../syntax/expansion/brace.md) syntax when looping over
|
||||||
numbers, and this form does not create leading zeroes unless you ask for
|
numbers, and this form does not create leading zeroes unless you ask for
|
||||||
them:
|
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
|
test command](../../commands/classictest.md)), with some additions and
|
||||||
extensions.
|
extensions.
|
||||||
|
|
||||||
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|Operator|Description|
|
||||||
Operator Description
|
|--|--|
|
||||||
-------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|`( <EXPRESSION> )`|Used to group expressions, to influence precedence of operators|
|
||||||
`( <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`!)|
|
||||||
`<EXPRESSION1> && <EXPRESSION2>` `TRUE` if `<EXPRESSION1>`**and**`<EXPRESSION2>` are `TRUE` (do **not** use `-a`!)
|
|`<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|
|
||||||
`<EXPRESSION1> || <EXPRESSION2>` `TRUE` if `<EXPRESSION1>`**or**`<EXPRESSION2>` is `TRUE` (do **not** use `-o`!)
|
|`<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|
|
||||||
`<STRING> == <PATTERN>` `<STRING>` is checked against the pattern `<PATTERN>` - `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.|
|
||||||
*But note¹, quoting the pattern forces a literal comparison.*
|
|See also [arithmetic comparisons](../../syntax/arith_expr.md#comparisons)|Using `(( <EXPRESSION> ))`, the [arithmetic expression compound command](../../syntax/ccmd/arithmetic_eval.md)|
|
||||||
|
|
||||||
`<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
|
When the `==` and `!=` operators are used, the string to the right of
|
||||||
the operator is considered a pattern and matched according to the rules
|
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
|
When the operators `<` and `>` are used (string collation order), the
|
||||||
test happens using the current locale when the `compat` level is greater
|
test happens using the current locale when the `compat` level is greater
|
||||||
than \"40\".
|
than "40".
|
||||||
|
|
||||||
Operator precedence (highest => lowest):
|
Operator precedence (highest => lowest):
|
||||||
|
|
||||||
@ -151,7 +140,7 @@ Example:
|
|||||||
|
|
||||||
### Behaviour differences compared to the builtin test command
|
### 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
|
strings lexicographically) use the current locale settings, while the
|
||||||
same primitives for the builtin test command don't. This leads to the
|
same primitives for the builtin test command don't. This leads to the
|
||||||
following situation where they behave differently:
|
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
|
- `[[ ... ]]` functionality isn't specified by POSIX(R), though it's
|
||||||
a reserved word
|
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
|
better term) which do have `[[`, the test expression compound
|
||||||
command is one of the very most portable non-POSIX features. Aside
|
command is one of the very most portable non-POSIX features. Aside
|
||||||
from the `=~` operator, almost every major feature is consistent
|
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 [list](../../syntax/basicgrammar.md#lists) `<LIST>` is simply executed in
|
||||||
the **current** shell environment. The list must be terminated with a
|
the **current** shell environment. The list must be terminated with a
|
||||||
**newline** or **semicolon**. For parsing reasons, the curly braces must
|
**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]
|
in the same line! [^1][^2]
|
||||||
|
|
||||||
This is known as a **group command**. The return status is the [exit
|
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
|
The [list](../../syntax/basicgrammar.md#lists) `<LIST>` is executed in a
|
||||||
separate shell - a subprocess. No changes to the environment (variables
|
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
|
## Examples
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
# Bash compound commands
|
# Bash compound commands
|
||||||
|
|
||||||
The main part of Bash's syntax are the so-called **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
|
commands](../../syntax/basicgrammar.md#simple_commands) or
|
||||||
[lists](../../syntax/basicgrammar.md#lists)) and knit some intelligence around
|
[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
|
## Command grouping
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ Note that conditionals can also be scripted using
|
|||||||
[list](../../syntax/basicgrammar.md#lists), which are syntax elements, not
|
[list](../../syntax/basicgrammar.md#lists), which are syntax elements, not
|
||||||
commands.
|
commands.
|
||||||
|
|
||||||
- the \"new\" test command: [conditional
|
- the "new" test command: [conditional
|
||||||
expression](conditional_expression.md)
|
expression](conditional_expression.md)
|
||||||
- if-clause: [conditional branching](if_clause.md)
|
- if-clause: [conditional branching](if_clause.md)
|
||||||
- case statement: [pattern-based branching](case.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):
|
using [declaration commands](../../commands/builtin/declare.md):
|
||||||
`declare -a 'pics=(img{'"$a..$b"'}.png)'; mv "${pics[@]}" ../imgs` This
|
`declare -a 'pics=(img{'"$a..$b"'}.png)'; mv "${pics[@]}" ../imgs` This
|
||||||
is significantly safer, but one must still be careful to control the
|
is significantly safer, but one must still be careful to control the
|
||||||
values of \$a and \$b. Both the exact quoting, and explicitly including
|
values of `$a` and `$b`. Both the exact quoting, and explicitly including
|
||||||
\"-a\" are important.
|
"`-a`" are important.
|
||||||
|
|
||||||
The brace expansion is present in two basic forms, **string lists** and
|
The brace expansion is present in two basic forms, **string lists** and
|
||||||
**ranges**.
|
**ranges**.
|
||||||
@ -87,24 +87,21 @@ With prefix or suffix strings, the result is a space-separated list of
|
|||||||
_I- _want- _my- _money- _back-
|
_I- _want- _my- _money- _back-
|
||||||
|
|
||||||
The brace expansion is only performed, if the given string list is
|
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,
|
(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
|
## Ranges
|
||||||
|
|
||||||
{<START>..<END>}
|
{<START>..<END>}
|
||||||
|
|
||||||
Brace expansion using ranges is written giving the startpoint and the
|
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
|
can be of two types
|
||||||
|
|
||||||
- integers (optionally zero padded, optionally with a given increment)
|
- integers (optionally zero padded, optionally with a given increment)
|
||||||
- characters
|
- characters
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
$ echo {5..12}
|
$ echo {5..12}
|
||||||
5 6 7 8 9 10 11 12
|
5 6 7 8 9 10 11 12
|
||||||
|
|
||||||
@ -186,13 +183,10 @@ for.
|
|||||||
|
|
||||||
mkdir /home/bash/test/{foo,bar,baz,cat,dog}
|
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:
|
- Using a prefix:
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
for i in 0{1..9} 10; do printf "%s\n" "$i";done
|
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
|
If you need to create words with the number embedded, you can use nested
|
||||||
@ -202,9 +196,6 @@ brace:
|
|||||||
|
|
||||||
- Formatting the numbers with printf:
|
- Formatting the numbers with printf:
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
echo $(printf "img%02d.png " {1..99})
|
echo $(printf "img%02d.png " {1..99})
|
||||||
|
|
||||||
See the [text below](#news_in_bash_4.0) for a new Bash 4 method.
|
See the [text below](#news_in_bash_4.0) for a new Bash 4 method.
|
||||||
@ -217,16 +208,16 @@ Can be written as
|
|||||||
|
|
||||||
somecommand -v{,,,,}
|
somecommand -v{,,,,}
|
||||||
|
|
||||||
\...which is a kind of a hack, but hey, it works.
|
...which is a kind of a hack, but hey, it works.
|
||||||
|
|
||||||
<div round info>
|
|
||||||
|
|
||||||
#### More fun
|
|
||||||
|
|
||||||
The most optimal possible brace expansion to expand n arguments of
|
!!! info "More fun"
|
||||||
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
|
The most optimal possible brace expansion to expand n arguments of
|
||||||
any number of arguments.
|
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.
|
||||||
|
|
||||||
function braceify {
|
function braceify {
|
||||||
[[ $1 == +([[:digit:]]) ]] || return
|
[[ $1 == +([[:digit:]]) ]] || return
|
||||||
@ -237,14 +228,13 @@ any number of arguments.
|
|||||||
|
|
||||||
printf 'eval printf "$arg"%s' "$(braceify 1000000)"
|
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
|
inject that output into a template which displays the most terse brace
|
||||||
expansion code that would expand `"$arg"` 1,000,000 times if evaluated.
|
expansion code that would expand `"$arg"` 1,000,000 times if evaluated.
|
||||||
In this case, the output is:
|
In this case, the output is:
|
||||||
|
|
||||||
eval printf "$arg"{,,}{,,}{,,}{,,}{,,}{,,}{,,,,,}{,,,,,}{,,,,,}{,,,,,}{,,,,,}{,,,,,}
|
eval printf "$arg"{,,}{,,}{,,}{,,}{,,}{,,}{,,,,,}{,,,,,}{,,,,,}{,,,,,}{,,,,,}{,,,,,}
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## New in Bash 4.0
|
## 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
|
splitting](../../syntax/expansion/wordsplit.md) and [pathname
|
||||||
expansion](../../syntax/expansion/globs.md). You have to remember that, because
|
expansion](../../syntax/expansion/globs.md). You have to remember that, because
|
||||||
the word splitting will also remove embedded newlines and other `IFS`
|
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
|
probably get unexpected pathname matches. **If you need the literal
|
||||||
results, quote the command substitution!**
|
results, quote the command substitution!**
|
||||||
|
|
||||||
The second form `` `COMMAND` `` is more or less obsolete for Bash, since
|
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!
|
escaped) and escaping characters. Use `$(COMMAND)`, it's also POSIX!
|
||||||
|
|
||||||
When you [call an explicit subshell](../../syntax/ccmd/grouping_subshell.md)
|
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
|
the following code snips to decide yourself which form you need under
|
||||||
specific circumstances:
|
specific circumstances:
|
||||||
|
|
||||||
**[Nesting]{.underline}**
|
**<u>Nesting</u>**
|
||||||
|
|
||||||
Backtick form `` `...` `` is not directly nestable. You will have to
|
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.
|
characters you need. Ugly.
|
||||||
|
|
||||||
echo `echo `ls`` # INCORRECT
|
echo `echo `ls`` # INCORRECT
|
||||||
echo `echo \`ls\`` # CORRECT
|
echo `echo \`ls\`` # CORRECT
|
||||||
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
|
All is based on the fact that the backquote-form is simple character
|
||||||
substitution, while every `$()`-construct opens an own, subsequent
|
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
|
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
|
It's not all shiny with `$()`, at least for my current Bash
|
||||||
(`3.1.17(1)-release`. :!: [**Update:** Fixed since `3.2-beta` together
|
(`3.1.17(1)-release`. :!: <u>**Update:** Fixed since `3.2-beta` together
|
||||||
with a misinterpretion of \'))\' being recognized as arithmetic
|
with a misinterpretion of '))' being recognized as arithmetic
|
||||||
expansion \[by redduck666\]]{.underline}). This command seems to
|
expansion by redduck666</u>). This command seems to
|
||||||
incorrectly close the substitution step and echo prints \"ls\" and
|
incorrectly close the substitution step and echo prints "ls" and
|
||||||
\")\":
|
")":
|
||||||
|
|
||||||
echo $(
|
echo $(
|
||||||
# some comment ending with a )
|
# some comment ending with a )
|
||||||
ls
|
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:
|
uncommon ;-)) construct like:
|
||||||
|
|
||||||
echo $(read VAR; case "$var" in foo) blah ;; esac) # spits out some error, when it sees the ";;"
|
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:
|
# fixes it:
|
||||||
echo $(read VAR; case "$var" in (foo) blah ;; esac) # will work, but just let it be, please ;-)
|
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:
|
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 "$var"; # $var == ""
|
||||||
var=$(echo -n $'\n'; echo -n x); var="${var%x}"; echo -n "$var" # $var == "\n"
|
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
|
This adds "x" to the output, which prevents the trailing newlines of
|
||||||
the previous commands\' output from being deleted by \$().
|
the previous commands' output from being deleted by `$()`.
|
||||||
|
|
||||||
By removing this \"x\" later on, we are left with the previous
|
By removing this "x" later on, we are left with the previous
|
||||||
commands\' output with its trailing newlines.
|
commands' output with its trailing newlines.
|
||||||
|
|
||||||
## See also
|
## See also
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
## General
|
## General
|
||||||
|
|
||||||
Unlike on other platforms you may have seen, on UNIX(r), the shell is
|
Unlike on other platforms you may have seen, on UNIX(r), the shell is
|
||||||
responsible for interpreting and expanding globs (\"filename
|
responsible for interpreting and expanding globs ("filename
|
||||||
wildcards\"). A called program will never see the glob itself; it will
|
wildcards"). A called program will never see the glob itself; it will
|
||||||
only see the expanded filenames as its arguments (here, all filenames
|
only see the expanded filenames as its arguments (here, all filenames
|
||||||
matching `*.log`):
|
matching `*.log`):
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ other `IFS`-characters they contain.
|
|||||||
corrections when matching directory names
|
corrections when matching directory names
|
||||||
- when the shell option `globstar` is set, the glob `**` will
|
- when the shell option `globstar` is set, the glob `**` will
|
||||||
recursively match all files and directories. This glob isn't
|
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.
|
recursively get all `*.c` filenames.
|
||||||
- when the shell option `globasciiranges` is set, the bracket-range
|
- when the shell option `globasciiranges` is set, the bracket-range
|
||||||
globs (e.g. `[A-Z]`) use C locale order rather than the configured
|
globs (e.g. `[A-Z]`) use C locale order rather than the configured
|
||||||
@ -56,7 +56,7 @@ other `IFS`-characters they contain.
|
|||||||
### nullglob
|
### nullglob
|
||||||
|
|
||||||
Normally, when no glob specified matches an existing filename, no
|
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:
|
removed:
|
||||||
|
|
||||||
$ echo "Textfiles here:" *.txt
|
$ echo "Textfiles here:" *.txt
|
||||||
@ -75,7 +75,7 @@ This can be very annoying, for example when you drive a
|
|||||||
done
|
done
|
||||||
|
|
||||||
When no file name matches the glob, the loop will not only output stupid
|
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.
|
with an error, since no file named `*.txt` exists.
|
||||||
|
|
||||||
Now, when the shell option `nullglob` is set, Bash will remove the
|
Now, when the shell option `nullglob` is set, Bash will remove the
|
||||||
@ -92,11 +92,11 @@ and the glob is gone.
|
|||||||
|
|
||||||
### Glob characters
|
### 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
|
(and depending on your settings, things like \'.\' may or may not be
|
||||||
matched, see above)
|
matched, see above)
|
||||||
- ? - means \'match any single character\'
|
- `?` - means \'match any single character\'
|
||||||
- \[abc\] - match any of the characters listed. This syntax also
|
- `[abc]` - match any of the characters listed. This syntax also
|
||||||
supports ranges, like \[0-9\]
|
supports ranges, like \[0-9\]
|
||||||
|
|
||||||
For example, to match something beginning with either \'S\' or \'K\'
|
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
|
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
|
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!
|
see `Hello world`, not the variable or anything else!
|
||||||
|
|
||||||
After all these expansions and substitutions are done, all quotes that
|
After all these expansions and substitutions are done, all quotes that
|
||||||
|
@ -42,21 +42,22 @@ from a file).
|
|||||||
|
|
||||||
### Scope
|
### Scope
|
||||||
|
|
||||||
<note important> Note: According to multiple comments and sources, the
|
!!! note "Note"
|
||||||
scope of process substitution file descriptors is **not** stable,
|
According to multiple comments and sources, the
|
||||||
guaranteed, or specified by bash. Newer versions of bash (5.0+) seem to
|
scope of process substitution file descriptors is **not** stable,
|
||||||
have shorter scope, and substitutions scope seems to be shorter than
|
guaranteed, or specified by bash. Newer versions of bash (5.0+) seem to
|
||||||
function scope. See
|
have shorter scope, and substitutions scope seems to be shorter than
|
||||||
[stackexchange](https://unix.stackexchange.com/questions/425456/conditional-process-substitution)
|
function scope. See
|
||||||
and
|
[stackexchange](https://unix.stackexchange.com/questions/425456/conditional-process-substitution)
|
||||||
[stackoverflow](https://stackoverflow.com/questions/46660020/bash-what-is-the-scope-of-the-process-substitution);
|
and
|
||||||
the latter discussion contains a script that can test the scoping
|
[stackoverflow](https://stackoverflow.com/questions/46660020/bash-what-is-the-scope-of-the-process-substitution);
|
||||||
behavior case-by-case </note>
|
the latter discussion contains a script that can test the scoping
|
||||||
|
behavior case-by-case
|
||||||
|
|
||||||
If a process substitution is expanded as an argument to a function,
|
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 an environment variable during calling of a function, or
|
||||||
expanded to any assignment within a function, the process substitution
|
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
|
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,
|
variable is set again within a callee, unless the new variable is local,
|
||||||
the previous process substitution is closed and will be unavailable to
|
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
|
### Avoiding subshells
|
||||||
|
|
||||||
<WRAP center round info 60%> See Also:
|
!!! info "See Also"
|
||||||
[BashFAQ/024](http://mywiki.wooledge.org/BashFAQ/024) -- *I set
|
See Also:
|
||||||
variables in a loop that's in a pipeline. Why do they disappear after
|
[BashFAQ/024](http://mywiki.wooledge.org/BashFAQ/024) -- *I set
|
||||||
the loop terminates? Or, why can't I pipe data to read?* </WRAP>
|
variables in a loop that's in a pipeline. Why do they disappear after
|
||||||
|
the loop terminates? Or, why can't I pipe data to read?*
|
||||||
|
|
||||||
One of the most common uses for process substitutions is to avoid the
|
One of the most common uses for process substitutions is to avoid the
|
||||||
final subshell that results from executing a pipeline. The following is
|
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
|
subshell (in Bash, by default), which means `counter` is only
|
||||||
incremented within the subshell. When the pipeline finishes, the
|
incremented within the subshell. When the pipeline finishes, the
|
||||||
subshell is terminated, and the `counter` visible to `echo` is still at
|
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
|
Process substitution helps us avoid the pipe operator (the reason for
|
||||||
the subshell):
|
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
|
### Process substitution assigned to a parameter
|
||||||
|
|
||||||
This example demonstrates how process substitutions can be made to
|
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.
|
`f`'s argument to uppercase.
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
|
@ -44,24 +44,25 @@ Tilde expansion is also performed everytime a variable is assigned:
|
|||||||
- after **every** `:` (colon) in the assigned value:
|
- after **every** `:` (colon) in the assigned value:
|
||||||
`TARGET=file:~moonman/share`
|
`TARGET=file:~moonman/share`
|
||||||
|
|
||||||
<note info> As of now (Bash 4.3-alpha) the following constructs
|
!!! info "Note"
|
||||||
**also** works, though it's not a variable assignment:
|
As of now (Bash 4.3-alpha) the following constructs
|
||||||
|
**also** works, though it's not a variable assignment:
|
||||||
|
|
||||||
echo foo=~
|
echo foo=~
|
||||||
echo foo=:~
|
echo foo=:~
|
||||||
|
|
||||||
I don't know yet, if this is a bug or intended. </note>
|
I don't know yet, if this is a bug or intended.
|
||||||
|
|
||||||
This way you can correctly use the tilde expansion in your
|
This way you can correctly use the tilde expansion in your
|
||||||
[PATH](../../syntax/shellvars.md#PATH):
|
[PATH](../../syntax/shellvars.md#PATH):
|
||||||
|
|
||||||
PATH=~/mybins:~peter/mybins:$PATH
|
PATH=~/mybins:~peter/mybins:$PATH
|
||||||
|
|
||||||
**Spaces in the referenced pathes?** A construct like\...
|
**Spaces in the referenced pathes?** A construct like...
|
||||||
|
|
||||||
~/"my directory"
|
~/"my directory"
|
||||||
|
|
||||||
\...is perfectly valid and works!
|
...is perfectly valid and works!
|
||||||
|
|
||||||
## Home directory
|
## Home directory
|
||||||
|
|
||||||
@ -84,7 +85,7 @@ precedence:
|
|||||||
- expand to the home directory of the user executing the shell
|
- expand to the home directory of the user executing the shell
|
||||||
(operating system)
|
(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.
|
directory, at least regarding tilde expansion.
|
||||||
|
|
||||||
## Current working directory
|
## Current working directory
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# Word splitting
|
# Word splitting
|
||||||
|
|
||||||
FIXME to be continued!
|
!!! warning "FIXME"
|
||||||
|
to be continued!
|
||||||
|
|
||||||
Word splitting occurs once any of the following expansions are done (and
|
Word splitting occurs once any of the following expansions are done (and
|
||||||
only then!)
|
only then!)
|
||||||
@ -18,9 +19,9 @@ are **not double-quoted**!
|
|||||||
The `IFS` variable holds the characters that Bash sees as word
|
The `IFS` variable holds the characters that Bash sees as word
|
||||||
boundaries in this step. The default contains the characters
|
boundaries in this step. The default contains the characters
|
||||||
|
|
||||||
- <space>
|
- <space>
|
||||||
- <tab>
|
- <tab>
|
||||||
- <newline>
|
- <newline>
|
||||||
|
|
||||||
These characters are also assumed when IFS is **unset**. When `IFS` is
|
These characters are also assumed when IFS is **unset**. When `IFS` is
|
||||||
**empty** (nullstring), no word splitting is performed at all.
|
**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**.
|
This doesn't happen when the expansion results were **double-quoted**.
|
||||||
|
|
||||||
When a null-string (e.g., something that before expanded to
|
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
|
won't perform word splitting! In this case, the initial token parsing
|
||||||
is solely responsible.
|
is solely responsible.
|
||||||
|
|
||||||
|
@ -10,22 +10,22 @@ tags:
|
|||||||
- execution
|
- execution
|
||||||
---
|
---
|
||||||
|
|
||||||
FIXME work in progress\...
|
!!! warning "FIXME"
|
||||||
|
work in progress...
|
||||||
|
|
||||||
# Parsing and execution
|
# Parsing and execution
|
||||||
|
|
||||||
Nearly everything in [Bash grammar](../../syntax/basicgrammar.md) can be broken
|
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.
|
evaluate and execute is the simple command.
|
||||||
|
|
||||||
## Simple command expansion
|
## Simple command expansion
|
||||||
|
|
||||||
<div center round info 60%>
|
!!! info "info"
|
||||||
|
|
||||||
- <http://lists.gnu.org/archive/html/bug-bash/2013-01/msg00040.html>
|
- <http://lists.gnu.org/archive/html/bug-bash/2013-01/msg00040.html>
|
||||||
- <http://lists.research.att.com/pipermail/ast-developers/2013q2/002456.html>
|
- <http://lists.research.att.com/pipermail/ast-developers/2013q2/002456.html>
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
This step happens after the initial command line splitting.
|
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
|
<div center round info
|
||||||
60%><http://lists.gnu.org/archive/html/bug-bash/2013-01/msg00054.html></div>
|
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
|
#!/bin/sh
|
||||||
# This shell runs in POSIX mode!
|
# This shell runs in POSIX mode!
|
||||||
@ -95,8 +95,8 @@ The behavior regarding the variable assignment errors can be tested:
|
|||||||
|
|
||||||
echo POST
|
echo POST
|
||||||
|
|
||||||
**[This one terminates only the enclosing compound command (the
|
<u>**This one terminates only the enclosing compound command (the
|
||||||
`{ ...; }`):]{.underline}**
|
`{ ...; }`):**</u>
|
||||||
|
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# This shell runs in native Bash-mode!
|
# 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
|
execution environment, you can't really influence the main shell with
|
||||||
it (changing directory, setting variables).
|
it (changing directory, setting variables).
|
||||||
|
|
||||||
FIXME to be continued
|
!!! warning "FIXME"
|
||||||
|
to be continued
|
||||||
|
|
||||||
## See also
|
## See also
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ more information on buffering issues.
|
|||||||
|
|
||||||
#### background processes
|
#### 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.
|
which the `coproc` was started. They are not inherited by subshells.
|
||||||
|
|
||||||
Here is a not-so-meaningful illustration. Suppose we want to
|
Here is a not-so-meaningful illustration. Suppose we want to
|
||||||
@ -222,7 +222,7 @@ exec >&${tee[1]} 2>&1
|
|||||||
|
|
||||||
### Other shells
|
### 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
|
which all do approximately the same thing. ksh93 and mksh have virtually
|
||||||
identical syntax and semantics for coprocs. A *list* operator: `|&` is
|
identical syntax and semantics for coprocs. A *list* operator: `|&` is
|
||||||
added to the language which runs the preceding *pipeline* as a coprocess
|
added to the language which runs the preceding *pipeline* as a coprocess
|
||||||
@ -258,7 +258,7 @@ more. See
|
|||||||
more details
|
more details
|
||||||
|
|
||||||
The ability to use multiple coprocesses in Bash is considered
|
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
|
than one. This may be overridden at compile-time with the
|
||||||
`MULTIPLE_COPROCS` option. However, at this time there are still issues
|
`MULTIPLE_COPROCS` option. However, at this time there are still issues
|
||||||
-- see the above mailing list discussion.
|
-- 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
|
The pattern description language is relatively easy. Any character
|
||||||
that's not mentioned below matches itself. The `NUL` character may not
|
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.
|
literally, i.e., without their special meaning.
|
||||||
|
|
||||||
Do **not** confuse patterns with ***regular expressions***, because they
|
Do **not** confuse patterns with ***regular expressions***, because they
|
||||||
@ -34,30 +34,30 @@ share some symbols and do similar matching work.
|
|||||||
|
|
||||||
## Normal pattern language
|
## Normal pattern language
|
||||||
|
|
||||||
Sequence Description
|
|Sequence|Description|
|
||||||
---------- ----------------------------------------------------------------------------------------------------------------
|
|--------|-----------|
|
||||||
`*` Matches **any string**, including the null string (empty string)
|
|`*`|Matches **any string**, including the null string (empty string)|
|
||||||
`?` Matches any **single character**
|
|`?`|Matches any **single character**|
|
||||||
`X` Matches the character `X` which can be any character that has no special meaning
|
|`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
|
|`\X`|Matches the character `X`, where the character's special meaning is stripped by the backslash|
|
||||||
`\\` Matches a backslash
|
|`\\`|Matches a backslash|
|
||||||
`[...]` Defines a pattern **bracket expression** (see below). Matches any of the enclosed characters at this position.
|
|`[...]`|Defines a pattern **bracket expression** (see below). Matches any of the enclosed characters at this position.|
|
||||||
|
|
||||||
### Bracket expressions
|
### Bracket expressions
|
||||||
|
|
||||||
The bracket expression `[...]` mentioned above has some useful
|
The bracket expression `[...]` mentioned above has some useful
|
||||||
applications:
|
applications:
|
||||||
|
|
||||||
Bracket expression Description
|
|Bracket expression|Description|
|
||||||
---------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|------------------|-----------|
|
||||||
`[XYZ]` The \"normal\" bracket expression, matching either `X`, `Y` or `Z`
|
|`[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**!)
|
|`[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`
|
|`[[: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
|
|`[^...]`|A negating expression: It matches all the characters that are **not** in the bracket expression|
|
||||||
`[!...]` Equivalent to `[^...]`
|
|`[!...]`|Equivalent to `[^...]`|
|
||||||
`[]...]` or `[-...]` Used to include the characters `]` and `-` into the set, they need to be the first characters after the opening bracket
|
|`[]...]` 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!)
|
|`[=C=]`|Matches any character that is eqivalent to the collation weight of `C` (current locale!)|
|
||||||
`[[.SYMBOL.]]` Matches the collating symbol `SYMBOL`
|
|`[[.SYMBOL.]]`|Matches the collating symbol `SYMBOL`|
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
@ -66,23 +66,23 @@ Some simple examples using normal pattern matching:
|
|||||||
- Pattern `"Hello world"` matches
|
- Pattern `"Hello world"` matches
|
||||||
- `Hello world`
|
- `Hello world`
|
||||||
- Pattern `[Hh]"ello world"` matches
|
- Pattern `[Hh]"ello world"` matches
|
||||||
- => `Hello world`
|
- => `Hello world`
|
||||||
- => `hello world`
|
- => `hello world`
|
||||||
- Pattern `Hello*` matches (for example)
|
- Pattern `Hello*` matches (for example)
|
||||||
- => `Hello world`
|
- => `Hello world`
|
||||||
- => `Helloworld`
|
- => `Helloworld`
|
||||||
- => `HelloWoRlD`
|
- => `HelloWoRlD`
|
||||||
- => `Hello`
|
- => `Hello`
|
||||||
- Pattern `Hello world[[:punct:]]` matches (for example)
|
- Pattern `Hello world[[:punct:]]` matches (for example)
|
||||||
- => `Hello world!`
|
- => `Hello world!`
|
||||||
- => `Hello world.`
|
- => `Hello world.`
|
||||||
- => `Hello world+`
|
- => `Hello world+`
|
||||||
- => `Hello world?`
|
- => `Hello world?`
|
||||||
- Pattern
|
- Pattern
|
||||||
`[[.backslash.]]Hello[[.vertical-line.]]world[[.exclamation-mark.]]`
|
`[[.backslash.]]Hello[[.vertical-line.]]world[[.exclamation-mark.]]`
|
||||||
matches (using [collation
|
matches (using [collation
|
||||||
symbols](https://pubs.opengroup.org/onlinepubs/009696899/basedefs/xbd_chap07.html#tag_07_03_02_04))
|
symbols](https://pubs.opengroup.org/onlinepubs/009696899/basedefs/xbd_chap07.html#tag_07_03_02_04))
|
||||||
- => `\Hello|world!`
|
- => `\Hello|world!`
|
||||||
|
|
||||||
## Extended pattern language
|
## 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
|
understands some powerful patterns. A `<PATTERN-LIST>` is one or more
|
||||||
patterns, separated by the pipe-symbol (`PATTERN|PATTERN`).
|
patterns, separated by the pipe-symbol (`PATTERN|PATTERN`).
|
||||||
|
|
||||||
--------------------- ------------------------------------------------------------
|
|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 **zero or one** occurrence of the given patterns|
|
||||||
`+(<PATTERN-LIST>)` Matches **one or more** occurrences of the given patterns
|
|`*(<PATTERN-LIST>)`|Matches **zero or more** occurrences of the given patterns|
|
||||||
`@(<PATTERN-LIST>)` Matches **one** of the given patterns
|
|`+(<PATTERN-LIST>)`|Matches **one or more** occurrences of the given patterns|
|
||||||
`!(<PATTERN-LIST>)` Matches anything **except** one of the given patterns
|
|`@(<PATTERN-LIST>)`|Matches **one** of the given patterns|
|
||||||
--------------------- ------------------------------------------------------------
|
|`!(<PATTERN-LIST>)`|Matches anything **except** one of the given patterns|
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
**[Delete all but one specific file]{.underline}**
|
<u>**Delete all but one specific file**</u>
|
||||||
|
|
||||||
rm -f !(survivior.txt)
|
rm -f !(survivior.txt)
|
||||||
|
|
||||||
@ -108,15 +108,15 @@ patterns, separated by the pipe-symbol (`PATTERN|PATTERN`).
|
|||||||
|
|
||||||
### Related shell options
|
### Related shell options
|
||||||
|
|
||||||
option classification description
|
|option|classification|description|
|
||||||
------------------- ------------------------------------- -------------------------------------------------------------------------------
|
|------|--------------|-----------|
|
||||||
`dotglob` [globbing](../syntax/expansion/globs.md) see [Pathname expansion customization](../syntax/expansion/globs.md#Customization)
|
|`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
|
|`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)
|
|`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)
|
|`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
|
|`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)
|
|`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)
|
|`globasciiranges`|[globbing](../syntax/expansion/globs.md)|see [Pathname expansion customization](/syntax/expansion/globs.md#Customization)|
|
||||||
|
|
||||||
## Bugs and Portability considerations
|
## Bugs and Portability considerations
|
||||||
|
|
||||||
@ -152,12 +152,12 @@ to those described above.
|
|||||||
|
|
||||||
\* ksh93 supports arbitrary quantifiers just like ERE using the
|
\* ksh93 supports arbitrary quantifiers just like ERE using the
|
||||||
`{from,to}(pattern-list)` syntax. `{2,4}(foo)bar` matches between 2-4
|
`{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". `{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". You can probably figure out the rest. So
|
||||||
far, none of the other shells support this syntax.
|
far, none of the other shells support this syntax.
|
||||||
|
|
||||||
\* In ksh93, a `pattern-list` may be delimited by either `&` or `|`. `&`
|
\* 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
|
example, `[[ fo0bar == @(fo[0-9]&+([[:alnum:]]))bar ]]` would be true
|
||||||
while `[[ f00bar == @(fo[0-9]&+([[:alnum:]]))bar ]]` is false, because
|
while `[[ f00bar == @(fo[0-9]&+([[:alnum:]]))bar ]]` is false, because
|
||||||
all members of the and-list must be satisfied. No other shell supports
|
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).
|
[article about arrays](../syntax/arrays.md).
|
||||||
|
|
||||||
For a more technical view what a parameter is and which types exist,
|
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
|
## 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
|
advantage that it can be immediately followed by characters that would
|
||||||
be interpreted as part of the parameter name otherwise. Compare these
|
be interpreted as part of the parameter name otherwise. Compare these
|
||||||
two expressions (`WORD="car"` for example), where we want to print a
|
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 $WORDs"
|
||||||
echo "The plural of $WORD is most likely ${WORD}s"
|
echo "The plural of $WORD is most likely ${WORD}s"
|
||||||
|
|
||||||
[Why does the first one fail?]{.underline} It prints nothing, because a
|
<u>Why does the first one fail?</u> It prints nothing, because a
|
||||||
parameter (variable) named \"`WORDs`\" is undefined and thus printed as
|
parameter (variable) named "`WORDs`" is undefined and thus printed as
|
||||||
\"\" (*nothing*). Without using braces for parameter expansion, Bash
|
"" (*nothing*). Without using braces for parameter expansion, Bash
|
||||||
will interpret the sequence of all valid characters from the introducing
|
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
|
using braces you just force Bash to **only interpret the name inside
|
||||||
your braces**.
|
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
|
normal parameter, for the mass expansion, please read the article about
|
||||||
arrays linked above.
|
arrays linked above.
|
||||||
|
|
||||||
- \${array\[5\]}
|
- `${array[5]}`
|
||||||
- \${array\[\*\]}
|
- `${array[*]}`
|
||||||
- \${array\[@\]}
|
- `${array[@]}`
|
||||||
|
|
||||||
## Indirection
|
## Indirection
|
||||||
|
|
||||||
@ -158,7 +158,7 @@ you can instead use the form
|
|||||||
|
|
||||||
to enter a level of indirection. The referenced parameter is not
|
to enter a level of indirection. The referenced parameter is not
|
||||||
`PARAMETER` itself, but the parameter whose name is stored as the value
|
`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
|
then `${!PARAMETER}` will expand to the value of the parameter named
|
||||||
`TEMP`:
|
`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)
|
indirectly (see [syntax/arrays#indirection](../syntax/arrays.md#indirection)
|
||||||
for workarounds). Additionally, the `!`-prefixed parameter expansion
|
for workarounds). Additionally, the `!`-prefixed parameter expansion
|
||||||
conflicts with ksh-like shells which have the more powerful
|
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.
|
used to expand to the name of the variable being referenced.
|
||||||
|
|
||||||
Indirect references to [array names](../syntax/arrays.md) are also possible
|
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>
|
</wrap>
|
||||||
|
|
||||||
[**Example: Rename all `*.txt` filenames to lowercase**]{.underline}
|
<u>**Example: Rename all `*.txt` filenames to lowercase**</u>
|
||||||
|
|
||||||
for file in *.txt; do
|
for file in *.txt; do
|
||||||
mv "$file" "${file,,}"
|
mv "$file" "${file,,}"
|
||||||
done
|
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
|
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
|
aspect of the Bash 4 release. Bash version 4, RC1 would perform word
|
||||||
splitting, and then case modification, resulting in title case (where
|
splitting, and then case modification, resulting in title case (where
|
||||||
@ -271,9 +271,6 @@ Assume: `array=(This is some Text)`
|
|||||||
- `echo "${array[@]^^}"`
|
- `echo "${array[@]^^}"`
|
||||||
- => `THIS IS SOME TEXT`
|
- => `THIS IS SOME TEXT`
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
* ''echo "${array[2]^^}"''
|
* ''echo "${array[2]^^}"''
|
||||||
* => ''SOME''
|
* => ''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).
|
character in the `IFS`-variable (<space> by default).
|
||||||
|
|
||||||
This will show all defined variable names (not values!) beginning with
|
This will show all defined variable names (not values!) beginning with
|
||||||
\"BASH\":
|
"BASH":
|
||||||
|
|
||||||
$ echo ${!BASH*}
|
$ echo ${!BASH*}
|
||||||
BASH BASH_ARGC BASH_ARGV BASH_COMMAND BASH_LINENO BASH_SOURCE BASH_SUBSHELL BASH_VERSINFO BASH_VERSION
|
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}`
|
`${PARAMETER#PATTERN}` and `${PARAMETER##PATTERN}`
|
||||||
|
|
||||||
This form is to remove the described [pattern](../syntax/pattern.md) trying
|
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
|
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~~,
|
following examples to get the idea (matched text ~~marked striked~~,
|
||||||
remember it will be removed!):
|
remember it will be removed!):
|
||||||
|
|
||||||
@ -347,7 +344,7 @@ from the end.
|
|||||||
|
|
||||||
### Common use
|
### 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
|
Well, maybe the most common use for it is to **extract parts of a
|
||||||
filename**. Just look at the following list with examples:
|
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
|
occurrence** of the given pattern, the second one (*two slashes*) is to
|
||||||
substitute **all occurrences** of the pattern.
|
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:
|
example string:
|
||||||
|
|
||||||
${MYSTRING//conservative/happy}
|
${MYSTRING//conservative/happy}
|
||||||
@ -418,26 +415,26 @@ example string:
|
|||||||
=>
|
=>
|
||||||
`Be liberal in what you accept, and conservativehappy in what you send`
|
`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.
|
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,
|
Let's play with the word "in", I don't know if it makes any sense,
|
||||||
but let's substitute it with \"by\".
|
but let's substitute it with "by".
|
||||||
|
|
||||||
[**First form: Substitute first occurrence**]{.underline}
|
<u>**First form: Substitute first occurrence**</u>
|
||||||
|
|
||||||
${MYSTRING/in/by}
|
${MYSTRING/in/by}
|
||||||
|
|
||||||
=> `Be liberal inby what you accept, and conservative in what you send`
|
=> `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}
|
${MYSTRING//in/by}
|
||||||
|
|
||||||
=>
|
=>
|
||||||
`Be liberal inby what you accept, and conservative inby what you send`
|
`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
|
expression: A `#` (hashmark) will indicate that your expression is
|
||||||
matched against the beginning portion of the string, a `%`
|
matched against the beginning portion of the string, a `%`
|
||||||
(percent-sign) will do it for the end portion.
|
(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"
|
MYSTRING="Be liberal in what you accept, and conservative in what you send"
|
||||||
|
|
||||||
Using echo `${#MYSTRING}`\...
|
Using echo `${#MYSTRING}`...
|
||||||
|
|
||||||
=> `64`
|
=> `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 [arrays](../syntax/arrays.md), this expansion type has two meanings:
|
||||||
|
|
||||||
- For **individual** elements, it reports the string length of the
|
- 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
|
- For the **mass subscripts** `@` and `*` it reports the number of set
|
||||||
elements in the array
|
elements in the array
|
||||||
|
|
||||||
@ -502,11 +499,11 @@ Example:
|
|||||||
Assume: `array=(This is a text)`
|
Assume: `array=(This is a text)`
|
||||||
|
|
||||||
- `echo ${#array[1]}`
|
- `echo ${#array[1]}`
|
||||||
- => 2 (the word \"is\" has a length of 2)
|
- => 2 (the word "is" has a length of 2)
|
||||||
- `echo ${#array[@]}`
|
- `echo ${#array[@]}`
|
||||||
- => 4 (the array contains 4 elements)
|
- => 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,
|
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
|
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
|
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)`
|
Assume: `array=(This is a text)`
|
||||||
|
|
||||||
- `echo ${array[0]:2:2}`
|
- `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}`
|
- `echo ${array[@]:1:2}`
|
||||||
- => `is a` (from element 1 inclusive, 2 elements are expanded,
|
- => `is a` (from element 1 inclusive, 2 elements are expanded,
|
||||||
i.e. element 1 and 2)
|
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
|
read -p "Enter your gender (just press ENTER to not tell us): " GENDER
|
||||||
echo "Your gender is ${GENDER:-a secret}."
|
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
|
gender. Note that the default value is **used on expansion time**, it is
|
||||||
**not assigned to the parameter**.
|
**not assigned to the parameter**.
|
||||||
|
|
||||||
@ -712,7 +709,7 @@ Let's change our code example from above:
|
|||||||
### Assign a default value: Arrays
|
### Assign a default value: Arrays
|
||||||
|
|
||||||
For [arrays](../syntax/arrays.md) this expansion type is limited. For an
|
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
|
default value is assigned to this one element. The mass-expansion
|
||||||
subscripts `@` and `*` **can not be used here** because it's not
|
subscripts `@` and `*` **can not be used here** because it's not
|
||||||
possible to assign to them!
|
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
|
The above code will simply add a warning if `JAVAPATH` is set (because
|
||||||
it could influence the startup behaviour of that imaginary application).
|
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
|
reason), and then, if they were set, print a warning and also print the
|
||||||
flags:
|
flags:
|
||||||
|
|
||||||
@ -761,7 +758,7 @@ if variables you need (and that can be empty) are undefined:
|
|||||||
### Use an alternate value: Arrays
|
### Use an alternate value: Arrays
|
||||||
|
|
||||||
Similar to the cases for [arrays](../syntax/arrays.md) to expand to a default
|
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
|
individual array elements by index, but reacts differently when using
|
||||||
the mass-expansion subscripts `@` and `*`:
|
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>
|
<a b cfoo> <a b cfoo> <a> <b> <cfoo>
|
||||||
`
|
`
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
- Almost all shells disagree about the treatment of an unquoted `$@`,
|
- Almost all shells disagree about the treatment of an unquoted `$@`,
|
||||||
`${arr[@]}`, `$*`, and `${arr[*]}` when
|
`${arr[@]}`, `$*`, and `${arr[*]}` when
|
||||||
[IFS](http://mywiki.wooledge.org/IFS) is set to null. POSIX is
|
[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
|
pathname expansion and word-splitting to the results, except for
|
||||||
zsh, which doesn't do pathname expansion in its default mode.
|
zsh, which doesn't do pathname expansion in its default mode.
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
- Additionally, shells disagree about various wordsplitting behaviors,
|
- Additionally, shells disagree about various wordsplitting behaviors,
|
||||||
the behavior of inserting delimiter characters from IFS in `$*`, and
|
the behavior of inserting delimiter characters from IFS in `$*`, and
|
||||||
the way adjacent arguments are concatenated, when IFS is modified in
|
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
|
possible side-effect that can affect expansion halfway through
|
||||||
expansion that way.
|
expansion that way.
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
- As previously mentioned, the Bash form of indirection by prefixing a
|
- As previously mentioned, the Bash form of indirection by prefixing a
|
||||||
parameter expansion with a `!` conflicts with the same syntax used
|
parameter expansion with a `!` conflicts with the same syntax used
|
||||||
by mksh, zsh, and ksh93 for a different purpose. Bash will
|
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.
|
addition of namerefs.
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
- Bash (and most other shells) don't allow .'s in identifiers. In
|
- Bash (and most other shells) don't allow .'s in identifiers. In
|
||||||
ksh93, dots in variable names are used to reference methods (i.e.
|
ksh93, dots in variable names are used to reference methods (i.e.
|
||||||
\"Discipline Functions\"), attributes, special shell variables, and
|
"Discipline Functions"), attributes, special shell variables, and
|
||||||
to define the \"real value\" of an instance of a class.
|
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
|
- In ksh93, the `_` parameter has even more uses. It is used in the
|
||||||
same way as `self` in some object-oriented languages; as a
|
same way as `self` in some object-oriented languages; as a
|
||||||
placeholder for some data local to a class; and also as the
|
placeholder for some data local to a class; and also as the
|
||||||
mechanism for class inheritance. In most other contexts, `_` is
|
mechanism for class inheritance. In most other contexts, `_` is
|
||||||
compatible with Bash.
|
compatible with Bash.
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
- Bash only evaluates the subscripts of the slice expansion
|
- Bash only evaluates the subscripts of the slice expansion
|
||||||
(`${x:y:z}`) if the parameter is set (for both nested expansions and
|
(`${x:y:z}`) if the parameter is set (for both nested expansions and
|
||||||
arithmetic). For ranges, Bash evaluates as little as possible, i.e.,
|
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
|
### 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
|
expansion that expands to multiple words, and nesting such
|
||||||
expansions, not all combinations of nested quoting are possible.
|
expansions, not all combinations of nested quoting are possible.
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
# Bash
|
# Bash
|
||||||
$ typeset -a a=(meh bleh blerg) b
|
$ typeset -a a=(meh bleh blerg) b
|
||||||
$ IFS=e
|
$ IFS=e
|
||||||
@ -1007,7 +983,7 @@ Consider the following (only slightly far-fetched) code:
|
|||||||
|
|
||||||
"${someCmd[@]-"$someOtherCmd" arg2 "${otherArgs[@]}"}" arg5
|
"${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
|
cases were this type of logic can be desirable and realistic. We can
|
||||||
deduce what was intended:
|
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.**
|
control over parsing, expansion and expansion results.**
|
||||||
|
|
||||||
Besides these basic variants, there are some special quoting methods
|
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 `'`,
|
:!: **ATTENTION** :!: The quote characters (`"`, double quote and `'`,
|
||||||
single quote) are a syntax element that influence parsing. It is not
|
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
|
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).
|
(see below).
|
||||||
|
|
||||||
## Weak quoting
|
## 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)
|
Will work as expected. `$PATH` is expanded, because it's double (weak)
|
||||||
quoted.
|
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
|
ways to deal with it
|
||||||
|
|
||||||
- if the baskslash is followed by a character that would have a
|
- 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
|
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
|
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
|
# WRONG
|
||||||
echo 'Here's my test...'
|
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`:
|
where the following escape sequences are decoded in `string`:
|
||||||
|
|
||||||
Code Meaning
|
|Code|Meaning|
|
||||||
-------------- -------------------------------------------------------------------------------------------------------------------------------------
|
|----|-------|
|
||||||
`\"` double-quote
|
|`\"`|double-quote|
|
||||||
`\'` single-quote
|
|`\'`|single-quote|
|
||||||
`\\` backslash
|
|`\\`|backslash|
|
||||||
`\a` terminal alert character (bell)
|
|`\a`|terminal alert character (bell)|
|
||||||
`\b` backspace
|
|`\b`|backspace|
|
||||||
`\e` escape (ASCII 033)
|
|`\e`|escape (ASCII 033)|
|
||||||
`\E` escape (ASCII 033) **\\E is non-standard**
|
|`\E`|escape (ASCII 033) **\E is non-standard**|
|
||||||
`\f` form feed
|
|`\f`|form feed|
|
||||||
`\n` newline
|
|`\n`|newline|
|
||||||
`\r` carriage return
|
|`\r`|carriage return|
|
||||||
`\t` horizontal tab
|
|`\t`|horizontal tab|
|
||||||
`\v` vertical tab
|
|`\v`|vertical tab|
|
||||||
`\cx` a control-x character, for example, `$'\cZ'` to print the control sequence composed of Ctrl-Z (`^Z`)
|
|`\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)
|
|`\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)
|
|`\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)
|
|`\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)
|
|`\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
|
This is especially useful when you want to pass special characters as
|
||||||
arguments to some programs, like passing a newline to sed.
|
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
|
shells including pdksh. A
|
||||||
[specification](http://austingroupbugs.net/view.php?id=249#c590) for it
|
[specification](http://austingroupbugs.net/view.php?id=249#c590) for it
|
||||||
was accepted for SUS issue 7. There are still some stragglers, such as
|
was accepted for SUS issue 7. There are still some stragglers, such as
|
||||||
most ash variants including dash, (except busybox built with \"bash
|
most ash variants including dash, (except busybox built with "bash
|
||||||
compatibility\" features).
|
compatibility" features).
|
||||||
|
|
||||||
## I18N/L10N
|
## I18N/L10N
|
||||||
|
|
||||||
@ -197,7 +197,7 @@ quoted string.
|
|||||||
|
|
||||||
If the string was replaced (translated), the result is double quoted.
|
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 `gettext()` or `_()`.
|
||||||
|
|
||||||
For useful examples to localize your scripts, please see [Appendix I of
|
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"
|
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
|
for animal in "$mylist"; do
|
||||||
echo $animal
|
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
|
is seen as **one word**. The for loop iterates exactly one time, with
|
||||||
`animal` set to the whole list.
|
`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
|
for animal in $mylist; do
|
||||||
echo $animal
|
echo $animal
|
||||||
@ -251,7 +251,7 @@ test string with spaces:
|
|||||||
|
|
||||||
mystring="my string"
|
mystring="my string"
|
||||||
|
|
||||||
And now check that string against the word \"testword\":
|
And now check that string against the word "testword":
|
||||||
|
|
||||||
[ $mystring = testword ] # WRONG!
|
[ $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
|
Now the command has three parameters, which makes sense for a binary
|
||||||
(two argument) operator.
|
(two argument) operator.
|
||||||
|
|
||||||
**[Hint:]{.underline}** Inside the [conditional
|
**<u>Hint:</u>** Inside the [conditional
|
||||||
expression](../syntax/ccmd/conditional_expression.md) (`[[ ]]`) Bash doesn't
|
expression](../syntax/ccmd/conditional_expression.md) (`[[ ]]`) Bash doesn't
|
||||||
perform word splitting, and thus you don't need to quote your variable
|
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
|
## 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: [Word splitting](../syntax/expansion/wordsplit.md)
|
||||||
- Internal: [Introduction to expansions and
|
- Internal: [Introduction to expansions and
|
||||||
substitutions](../syntax/expansion/intro.md)
|
substitutions](../syntax/expansion/intro.md)
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
- External: [Grymore:
|
- External: [Grymore:
|
||||||
Shellquoting](http://www.grymoire.com/Unix/Quote.html)
|
Shellquoting](http://www.grymoire.com/Unix/Quote.html)
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
# Redirection
|
# 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
|
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
|
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
|
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
|
Under normal circumstances, there are 3 files open, accessible by the
|
||||||
file descriptors 0, 1 and 2, all connected to your terminal:
|
file descriptors 0, 1 and 2, all connected to your terminal:
|
||||||
|
|
||||||
Name FD Description
|
|Name|FD|Description|
|
||||||
---------- ---- --------------------------------------------------------
|
|----|--|-----------|
|
||||||
`stdin` 0 standard input stream (e.g. keyboard)
|
|`stdin`|0|standard input stream (e.g. keyboard)|
|
||||||
`stdout` 1 standard output stream (e.g. monitor)
|
|`stdout`|1|standard output stream (e.g. monitor)|
|
||||||
`stderr` 2 standard error output stream (usually also on monitor)
|
|`stderr`|2|standard error output stream (usually also on monitor)|
|
||||||
|
|
||||||
<wrap center info>The terms \"monitor\" and \"keyboard\" refer to the
|
|
||||||
same device, the **terminal** here. Check your preferred UNIX(r)-FAQ for
|
|
||||||
details, I\'m too lazy to explain what a terminal is ;-) </wrap>
|
!!! info "INFO"
|
||||||
|
The terms "monitor" and "keyboard" refer to the
|
||||||
|
same device, the **terminal** here. Check your preferred UNIX(r)-FAQ for
|
||||||
|
details, I'm too lazy to explain what a terminal is ;-)
|
||||||
|
|
||||||
Both, `stdout` and `stderr` are output file descriptors. Their
|
Both, `stdout` and `stderr` are output file descriptors. Their
|
||||||
difference is the **convention** that a program outputs payload on
|
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
|
cat some_file.txt 2>/dev/null
|
||||||
|
|
||||||
Whenever you **reference** a descriptor, to point to its current target
|
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
|
# this executes the echo-command and redirects its normal output (stdout) to the standard error target
|
||||||
echo "There was an error" 1>&2
|
echo "There was an error" 1>&2
|
||||||
@ -45,26 +50,27 @@ these examples are equivalent:
|
|||||||
cat >new.txt foo.txt bar.txt
|
cat >new.txt foo.txt bar.txt
|
||||||
>new.txt cat foo.txt bar.txt
|
>new.txt cat foo.txt bar.txt
|
||||||
|
|
||||||
<wrap center important>Every redirection operator takes one or two
|
!!! info "important"
|
||||||
words as operands. If you have to use operands (e.g. filenames to
|
Every redirection operator takes one or two
|
||||||
redirect to) that contain spaces you **must** quote them!</wrap>
|
words as operands. If you have to use operands (e.g. filenames to
|
||||||
|
redirect to) that contain spaces you **must** quote them!
|
||||||
|
|
||||||
## Valid redirection targets and sources
|
## Valid redirection targets and sources
|
||||||
|
|
||||||
This syntax is recognized whenever a `TARGET` or a `SOURCE`
|
This syntax is recognized whenever a `TARGET` or a `SOURCE`
|
||||||
specification (like below in the details descriptions) is used.
|
specification (like below in the details descriptions) is used.
|
||||||
|
|
||||||
Syntax Description
|
|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)
|
|`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)
|
|`&N`|references the current target/source of the filedescriptor `N` ("duplicates" the filedescriptor)|
|
||||||
`&-` closes the redirected filedescriptor, useful instead of `> /dev/null` constructs (`> &-`)
|
|`&-`|closes the redirected filedescriptor, useful instead of `> /dev/null` constructs (`> &-`)|
|
||||||
`/dev/fd/N` duplicates the filedescriptor `N`, if `N` is a valid integer
|
|`/dev/fd/N`|duplicates the filedescriptor `N`, if `N` is a valid integer|
|
||||||
`/dev/stdin` duplicates filedescriptor 0 (`stdin`)
|
|`/dev/stdin`|duplicates filedescriptor 0 (`stdin`)|
|
||||||
`/dev/stdout` duplicates filedescriptor 1 (`stdout`)
|
|`/dev/stdout`|duplicates filedescriptor 1 (`stdout`)|
|
||||||
`/dev/stderr` duplicates filedescriptor 2 (`stderr`)
|
|`/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/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
|
|`/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
|
If a target/source specification fails to open, the whole redirection
|
||||||
operation fails. Avoid referencing file descriptors above 9, since you
|
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
|
Since Bash4, there's `&>>TARGET`, which is equivalent to
|
||||||
`>> TARGET 2>&1`.
|
`>> TARGET 2>&1`.
|
||||||
|
|
||||||
<wrap center important>This syntax is deprecated and should not be
|
!!! info "important"
|
||||||
used. See the page about [obsolete and deprecated
|
This syntax is deprecated and should not be
|
||||||
syntax](../scripting/obsolete.md).</wrap>
|
used. See the page about [obsolete and deprecated
|
||||||
|
syntax](../scripting/obsolete.md).
|
||||||
|
|
||||||
## Appending redirected output and error output
|
## Appending redirected output and error output
|
||||||
|
|
||||||
@ -145,7 +152,7 @@ omitted, filedescriptor 0 (`stdin`) is assumed.
|
|||||||
TAG
|
TAG
|
||||||
|
|
||||||
A here-document is an input redirection using source data specified
|
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
|
The redirection-operator `<<` is used together with a tag `TAG` that's
|
||||||
used to mark the end of input later:
|
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
|
The tag you use **must** be the only word in the line, to be recognized
|
||||||
as end-of-here-document marker.
|
as end-of-here-document marker.
|
||||||
|
|
||||||
<wrap center info>It seems that here-documents (tested on versions
|
!!! info "info"
|
||||||
`1.14.7`, `2.05b` and `3.1.17`) are correctly terminated when there is
|
It seems that here-documents (tested on versions
|
||||||
an EOF before the end-of-here-document tag. The reason is unknown, but
|
`1.14.7`, `2.05b` and `3.1.17`) are correctly terminated when there is
|
||||||
it seems to be done on purpose. Bash 4 introduced a warning message when
|
an EOF before the end-of-here-document tag. The reason is unknown, but
|
||||||
end-of-file is seen before the tag is reached.</wrap>
|
it seems to be done on purpose. Bash 4 introduced a warning message when
|
||||||
|
end-of-file is seen before the tag is reached.
|
||||||
|
|
||||||
## Here strings
|
## Here strings
|
||||||
|
|
||||||
@ -201,7 +209,7 @@ The here-string will append a newline (`\n`) to the data.
|
|||||||
## Multiple redirections
|
## Multiple redirections
|
||||||
|
|
||||||
More redirection operations can occur in a line of course. The order is
|
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`,
|
redirect both, `stderr` and `stdout` to the same file (like `/dev/null`,
|
||||||
to hide it), this is **the wrong way**:
|
to hide it), this is **the wrong way**:
|
||||||
|
|
||||||
@ -216,12 +224,12 @@ Why? Relatively easy:
|
|||||||
- initially, `stdout` points to your terminal (you read it)
|
- initially, `stdout` points to your terminal (you read it)
|
||||||
- same applies to `stderr`, it's connected to your terminal
|
- same applies to `stderr`, it's connected to your terminal
|
||||||
- `2>&1` redirects `stderr` away from the terminal to the target for
|
- `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
|
- `1>/dev/null` redirects `stdout` away from your terminal to the file
|
||||||
`/dev/null`
|
`/dev/null`
|
||||||
|
|
||||||
What remains? `stdout` goes to `/dev/null`, `stderr` still (or better:
|
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:
|
do what you want:
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -10,12 +10,13 @@ tags:
|
|||||||
- recognition
|
- recognition
|
||||||
---
|
---
|
||||||
|
|
||||||
# Words\...
|
# Words...
|
||||||
|
|
||||||
FIXME This article needs a review, it covers two topics (command line
|
!!! warning "FIXME"
|
||||||
splitting and word splitting) and mixes both a bit too much. But in
|
This article needs a review, it covers two topics (command line
|
||||||
general, it's still usable to help understand this behaviour, it's
|
splitting and word splitting) and mixes both a bit too much. But in
|
||||||
\"wrong but not wrong\".
|
general, it's still usable to help understand this behaviour, it's
|
||||||
|
"wrong but not wrong".
|
||||||
|
|
||||||
One fundamental principle of Bash is to recognize words entered at the
|
One fundamental principle of Bash is to recognize words entered at the
|
||||||
command prompt, or under other circumstances like variable-expansion.
|
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
|
look for those special characters, and use them to separate the
|
||||||
parameters.
|
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
|
$ echo Hello little world
|
||||||
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
|
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
|
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
|
course not! Bash treats blanks as special characters, but there are two
|
||||||
ways to tell Bash not to treat them special: **Escaping** and
|
ways to tell Bash not to treat them special: **Escaping** and
|
||||||
**quoting**.
|
**quoting**.
|
||||||
@ -63,9 +64,9 @@ Escaping is done by preceeding the character with a backslash:
|
|||||||
Hello little world
|
Hello little world
|
||||||
|
|
||||||
None of the escaped spaces will be used to perform word splitting. Thus,
|
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
|
context of command-splitting, which this section is about, it doesn't
|
||||||
matter which kind of quoting you use: weak quoting or strong quoting,
|
matter which kind of quoting you use: weak quoting or strong quoting,
|
||||||
both cause Bash to not treat spaces as special characters:
|
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'
|
$ echo 'Hello little world'
|
||||||
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
|
program that expects a filename as an argument, like cat. Filenames can
|
||||||
have spaces in them:
|
have spaces in them:
|
||||||
|
|
||||||
@ -141,41 +142,37 @@ and the first review is:
|
|||||||
|
|
||||||
echo The file is named $MYFILE
|
echo The file is named $MYFILE
|
||||||
|
|
||||||
The parser will scan for blanks and mark the relevant words (\"splitting
|
The parser will scan for blanks and mark the relevant words ("splitting
|
||||||
the command line\"):
|
the command line"):
|
||||||
|
|
||||||
Initial command line splitting:
|
| Initial command line splitting: | | | | | |
|
||||||
--------------------------------- -------- -------- -------- --------- -----------
|
|---------------------------------|--------|--------|--------|---------|-----------|
|
||||||
Word 1 Word 2 Word 3 Word 4 Word 5 Word 6
|
| Word 1 | Word 2 | Word 3 | Word 4 | Word 5 | Word 6 |
|
||||||
`echo` `The` `file` `is` `named` `$MYFILE`
|
| `echo` | `The` | `file` | `is` | `named` | `$MYFILE` |
|
||||||
|
|
||||||
A [parameter/variable expansion](../syntax/pe.md) is part of that command
|
A [parameter/variable expansion](../syntax/pe.md) is part of that command
|
||||||
line, Bash will perform the substitution, and the [word
|
line, Bash will perform the substitution, and the [word
|
||||||
splitting](../syntax/expansion/wordsplit.md) on the results:
|
splitting](../syntax/expansion/wordsplit.md) on the results:
|
||||||
|
|
||||||
Word splitting after substitution:
|
| Word splitting after substitution: | | | | | | |
|
||||||
------------------------------------ -------- -------- -------- --------- -------- ------------
|
|------------------------------------|--------|--------|--------|---------|--------|------------|
|
||||||
Word 1 Word 2 Word 3 Word 4 Word 5 Word 6 Word 7
|
| Word 1 | Word 2 | Word 3 | Word 4 | Word 5 | Word 6 | Word 7 |
|
||||||
`echo` `The` `file` `is` `named` `THE` `FILE.TXT`
|
| `echo` | `The` | `file` | `is` | `named` | `THE` | `FILE.TXT` |
|
||||||
|
|
||||||
Now let's imagine we quoted `$MYFILE`, the command line now looks like:
|
Now let's imagine we quoted `$MYFILE`, the command line now looks like:
|
||||||
|
|
||||||
echo The file is named "$MYFILE"
|
echo The file is named "$MYFILE"
|
||||||
|
|
||||||
Word splitting after substitution (quoted!):
|
| Word splitting after substitution (quoted!): | | | | | |
|
||||||
---------------------------------------------- -------- -------- -------- --------- ----------------
|
|----------------------------------------------|--------|--------|--------|---------|----------------|
|
||||||
Word 1 Word 2 Word 3 Word 4 Word 5 Word 6
|
| Word 1 | Word 2 | Word 3 | Word 4 | Word 5 | Word 6 |
|
||||||
`echo` `The` `file` `is` `named` `THE FILE.TXT`
|
| `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: [Quoting and character escaping](../syntax/quoting.md)
|
||||||
- Internal: [Word splitting](../syntax/expansion/wordsplit.md)
|
- Internal: [Word splitting](../syntax/expansion/wordsplit.md)
|
||||||
- Internal: [Introduction to expansions and
|
- Internal: [Introduction to expansions and
|
||||||
substitutions](../syntax/expansion/intro.md)
|
substitutions](../syntax/expansion/intro.md)
|
||||||
|
|
||||||
```{=html}
|
|
||||||
<!-- -->
|
|
||||||
```
|
|
||||||
- External: [Grymore:
|
- External: [Grymore:
|
||||||
Shellquoting](http://www.grymoire.com/Unix/Quote.html)
|
Shellquoting](http://www.grymoire.com/Unix/Quote.html)
|
||||||
|
Loading…
Reference in New Issue
Block a user