Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Bash shift quirks.

Bash shift quirks

When using the shift built-in, have noted this interesting behavior which I have been unable to find documentation for.

Update: the answer was right in front of me, if shift is called with a value greater than arguments available in $1 - $x then it will return with a non zero status - hence the script will halt (since I'm using set -e)!

Using the script test.sh, executed using arguments:

./test.sh apple orange banana
apple
orange
banana

banana


red
blue

As expected:

  • Three arguments echoed.
  • Shift two away.
  • One remains as $1 (banana).

And then without arguments:

./test.sh

# no output

Arguments $1 - $3 don't exist, so no output or shift but $variable1 and $variable2 are now broken!?!

Why? I'm not sure. Appreciate any comments!

But what this does show, it's safer to check the number of positional arguments available before calling shift e.g.:

[[ $# -ge 2 ]] && shift 2

Reference

#!/bin/bash -e
echo "$1"
echo "$2"
echo "$3"
echo
shift 2
variable1="red"
variable2="blue"
echo "$1"
echo "$2"
echo "$3"
echo "$variable1"
echo "$variable2"
@bambam2174

This comment has been minimized.

Copy link

bambam2174 commented Aug 26, 2018

The reason for that behaviour ist the -e option in #!/bin/bash -e
It's like calling set -e which has the effect that a script exits immediately if any command exits with a non-zero status.
And if you shift more than the arguments / parameter count then the shift-command exits with a non-zero status.
That prevents executing any further commands after this shift-call.
If you omit the -e option at the beginning the following commands (echos) will get executed

@magnetikonline

This comment has been minimized.

Copy link
Owner Author

magnetikonline commented Aug 27, 2018

Of course @bambam2174 - and to be honest, that answer was right in front of me!!! 🤦‍♂

See here http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_09_07.html (which I linked to as well!).

The return status is zero unless N is greater than $# or less than zero; otherwise it is non-zero.

That was my own silly fault 🤕 - thanks for setting me right!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.