I like to be able to ... && add-arg 'something', and have 'something' be added to the positional arguments, kind of like an inverse shift.

I tried ... && set "$@ something", but this didn't work, though just doing set "$@ something" (without the condition) seemed to work correctly.

  • Hmm, the && conditional shouldn't matter. What would matter is if you run set in a subshell or in a function. (And of course set "$@ sth" just appends to the last positional parameter, instead of adding a new one.)
    – ilkkachu
    Jul 18 '19 at 16:42

In any POSIX shell,

set -- "$@" "value"

would add value to the end of the list of positional parameters (it would actually replace the list with a new longer list), and

set -- "value" "$@"

would add it in the beginning (and would technically be the reverse of a shift as shift removes the first element). This holds true for zsh.

The -- is used to protect the following values from accidentally being interpreted as options, in case they start with -.

The special variable $@ is almost exclusively used as "$@" as this would expand to the value of each positional parameter individually quoted. The expression "$@ somethingelse" would expand to the list of individually quoted positional parameters, with <space>somethingelse appended to the last of them.

To use the values of the positional parameters as a single string delimited by spaces (or whatever the first character of $IFS may be), use "$*" ("$* somethingelse" is well defined as a single string). This is however not what you want to do in this instance as it would collapse your list of values to one single value.

  • 2
    "$@ somethingelse" appends the string <space>somethingelse to the last positional parameter, and expands all of them as distinct fields. "...if the parameter being expanded was embedded within a word, the first field shall be joined with the beginning part of the original word and the last field shall be joined with the end part of the original word." (2.5.2 Special Parameters)
    – ilkkachu
    Jul 18 '19 at 16:35
  • 1
    @ilkkachu Thanks for that reference, I've been wondering about for a while now. I'll update the answer.
    – Kusalananda
    Jul 18 '19 at 16:42

With zsh specifically, in addition to the standard set -- "$@" ... shown by @Kusalananda, the positional parameters are also available via the $argv array (like in csh), so you can also do:

argv+=arg             # append one argument to the end
argv+=(arg2 arg3)     # append several arguments
argv[1,0]=(arg1 arg2) # insert in front
argv[3,0]=(x)         # insert before the 3rd element
2+=(x)                # same as above (insert after the 2nd)
2+=x                  # append x to the second argument (not to confuse with
                      # the above).
argv[2,5]=(y)         # replace 4 elements 2 to 5 with one y argument
argv[3,-1]=()         # truncate
1=()                  # same as "shift"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.