I am writing a zsh script, which is invoked with a variable number of arguments, such as
scriptname a b c d filename
Inside the script, I want first to loop over the arguments (except the last one) and process them, and finally do something with the processed data and the last argument (filename).
I got this working, but am not entirely happy with my solution. Here is what I came up with (where process
and apply
are some other scripts not relevant to my problem):
#!/bin/zsh
set -u
x=""
filename=$@[-1]
# Process initial arguments
for ((i=1; i<$#; i++))
do
x+=$(process ${@[$i]})
done
apply $x $filename
I find the counting loop too cumbersome. If filename
where the first argument, I would do a shift
and then could simply loop over the arguments, after having saved the filename. However I want to keep the filename as the last argument (for consistency with other tools).
Any ideas how to write this neatly without counting loop?
You can slice off the last argument from the original list and save them into an array, if thats an option
args=("${@:1:$# -1}")
for arg in "${args[@]}"; do # iterate over all, except the last
printf '%s\n' "$arg"
done
Using the array as a placeholder is optional as you can iterate over the arguments slice directly i.e. for arg in "${@:1:$# -1}"; do
. The syntax is even available in bash
also.
As pointed out by chepner's comment, you could use a zsh
specifc syntax as
for arg in $@[1,-2]; do
printf '%s\n' "$arg"
done