mirror of
https://github.com/flokoe/bash-hackers-wiki.git
synced 2024-11-25 15:53:41 +01:00
98 lines
2.7 KiB
Markdown
98 lines
2.7 KiB
Markdown
# The shift builtin command
|
|
|
|
## Synopsis
|
|
|
|
shift [n]
|
|
|
|
## Description
|
|
|
|
The `shift` builtin command is used to "shift" the positional
|
|
parameters by the given number `n` or by 1, if no number is given.
|
|
|
|
This means, the number and the position of the positional parameters are
|
|
changed. The very first positional parameter is discarded, the second
|
|
becomes the first one, etc.
|
|
|
|
Imagine the following set of positional parameters (`$1` to `$4`):
|
|
|
|
|Positional Parameter|Value|
|
|
|-|-|
|
|
|1|This
|
|
|2|is|
|
|
|3|a|
|
|
|4|test|
|
|
|
|
When you use `shift 1`, they will be changed to:
|
|
|
|
|Positional Parameter|Value|
|
|
|-|-|
|
|
|1|is|
|
|
|2|a|
|
|
|3|test|
|
|
|
|
The [special parameter](../../syntax/shellvars.md#special_parameters) `$#` will
|
|
reflect the final number of positional parameters.
|
|
|
|
If the number given is 0, no changes are made to the positional
|
|
parameters.
|
|
|
|
### Options
|
|
|
|
There are no options.
|
|
|
|
### Return status
|
|
|
|
|Status|Reason|
|
|
|------|------|
|
|
|0|no error|
|
|
|1|non-numeric argument|
|
|
|1|given number (or the default 1) is bigger than the number of actually present positional parameters|
|
|
|1|given number is negative|
|
|
|
|
## Examples
|
|
|
|
## Portability considerations
|
|
|
|
- The `shift` builtin command is specified by POSIX(r).
|
|
- Many shells will throw a fatal error when attempting to `shift` more
|
|
than the number of positional parameters. **POSIX does not require
|
|
that behavior**. Bash (even in POSIX mode) and Zsh return 1 when
|
|
there are no args, and no error output is produced unless the
|
|
[shift_verbose](../../internals/shell_options.md#shift_verbose)
|
|
[shopt](../../commands/builtin/shopt.md) option is enabled. Ksh93, pdksh,
|
|
posh, mksh, and dash, all throw useless fatal shell
|
|
errors.
|
|
```
|
|
$ dash -c 'f() { if shift; then echo "$1"; else echo "no args"; fi; }; f'
|
|
dash: 1: shift: can't shift that many
|
|
```
|
|
In most shells, you can work around this problem using the
|
|
`command` builtin to suppress fatal
|
|
errors caused by *special builtins*.
|
|
```
|
|
$ dash -c 'f() { if command shift 2>/dev/null; then echo "$1"; else echo "no args"; fi; }; f'
|
|
no args
|
|
```
|
|
While, POSIX requires this behavior, it isn't very
|
|
obvious and some shells don't do it correctly. To work around this, you
|
|
can use something like:
|
|
```
|
|
$ mksh -c 'f() { if ! ${1+false} && shift; then echo "$1"; else echo "no args"; fi; }; f'
|
|
no args
|
|
```
|
|
<del>The mksh maintainer refuses to change either the `shift` or `command` builtins.</del>
|
|
[Fixed](https://github.com/MirBSD/mksh/commit/996e05548ab82f7ef2dea61f109cc7b6d13837fa).
|
|
(Thanks!)
|
|
|
|
- Perhaps almost as bad as the above, busybox sh's `shift` always
|
|
returns success, even when attempting to shift beyond the final
|
|
argument.
|
|
```
|
|
$ bb -c 'f() { if shift; then echo "$1"; else echo "no args"; fi; }; f'
|
|
(no output)
|
|
```
|
|
The above mksh workaround will work in this case
|
|
too.
|
|
|
|
## See also
|