wiki.bash-hackers.org/commands/builtin/shift.md

88 lines
3.2 KiB
Markdown
Raw Permalink Normal View History

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