In bash/zsh we use $_ representing the last argument to the previous command for later use, but this parameter contains the "expanded version" as documented. is there a thing that I can have un-expanded version of that? like in below example:

printf "%s\n" something{1..3}

I want to have access to un-expanded something{1..3} argument in the later command, not only something3.

doing this way also still adds only to very last argument not for all.

bash -c '
   printf "%s\n" "$@" && printf "%s\n" "$@"-add-something-more;
' _ something{1..3}

same in zsh, is there a way to to get that without eval trick that I don't preferer to use this way but want to show what exactly I want to have?

bash -c '
    eval printf "%s\\\n" "$@" && eval printf "%s\\\n" "$@"-add-something-more;
' _ 'something{1..3}'


  • Reading from the history is not an option as commands would executing within script and arguments would passing to the script by a user.
  • I'm using command1 "$@" && command2 "$@"<question-part> syntax to execute command2 only if command1 was executed successfully.
  • In zsh: fc -n -l -1 | awk '{ print $NF }' (not an answer as I don't explain anything or say anything about bash; there are probably better ways too).
    – Kusalananda
    Dec 31, 2020 at 15:29
  • 1
    Ah, ok, that wasn't clear. Good.
    – Kusalananda
    Dec 31, 2020 at 15:42
  • Are you looking for something similar to insert-last-argument (M-., M-_) but that can be used non-interactively? Dec 31, 2020 at 15:52
  • @ArkadiuszDrabczyk yes, exactly and both to work in bash an zsh Dec 31, 2020 at 16:07
  • But that and history expansion does that outside of the shell syntax (it adds text to a string which is later fed to the shell parser), doing it as part of the shell syntax wouldn't make sense. Dec 31, 2020 at 16:11

1 Answer 1


To reuse a list of args more than once, that's typically what (anonymous) functions or variables are for.

In zsh:

() {cmd1 "$@" && cmd2 "$@"} something{1..3}
l=(something{1..3}); cmd1 $l && cmd2 $l

To add the same string to each argument, use the $^array syntax:

$ () {echo $@; echo $^@-more} a{1..3}
a1 a2 a3
a1-more a2-more a3-more

(the bash/ksh/zsh equivalent would be "${@/%/-more}").

To get an unexpanded version of $_, you could do something like:

TRAPDEBUG() last_cmd=($cur_cmd) cur_cmd=("${(z)ZSH_DEBUG_CMD}") 

And then:

$ echo a{1..3}; echo $last_cmd[-1]
a1 a2 a3

However note that the DEBUG trap is executed before each sublist, not pipeline, let alone command. So that wouldn't work for echo a{1..3} && echo $last_cmd[-1]. You'd need:

$ eval 'echo a{1..3}' && eval 'echo $last_cmd[-1]'
a1 a2 a3

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.