While most programming languages are accepting arguments as an array of strings, shell doesn’t
arglist.c
#include
int main(int argc, char **argv) {
int i;
for (i=1; argc>i; i++)
printf("$%d=%s\n",i,argv[i]);
}
$ make arglist
cc arglist.c -o arglist
$ ./arglist one two three four
$1=one
$2=two
$3=three
$4=four
To do the same in shell, it requires some dynamic evaluation, for instance with eval
arglist.sh
i=1
while [ $i -le $# ]
do
eval ARGV[$i]=\$$i
echo "\$$i=$(eval echo \"\${ARGV[$i]}\")"
((i+=1))
done
$ ./arglist.sh one two three four
$1=one
$2=two
$3=three
$4=four
To further send the arguments to another script or function, it is important to take consideration of white spaces and file expansion (e.g.: *.*), this is achieved with double-quotes and the at-sign
f "${ARGV[@]}"
I recommend against using eval whenever possible. While less awesome, I would prefer something more verbose and without eval
arglist2.sh
[ -n "$1" ] && echo "\$1=$1"
[ -n "$2" ] && echo "\$2=$2"
[ -n "$3" ] && echo "\$3=$3"
[ -n "$4" ] && echo "\$4=$4"
[ -n "$5" ] && echo "\$5=$5"
$ ./arglist2.sh one two three four
$1=one
$2=two
$3=three
$4=four
Using eval is difficult and dangerous. The innocent may messed up with the quotes resulting in random effects. It is also a common source of code injection
inj.sh
eval x=$1
$ ./inj.sh 1
$ ./inj.sh "1; echo uh-oh"
uh-oh
Ref: Eval Injection
You can avoid eval by using the shift operator:
i=1
while [ -n “$1” ]
do
echo \$$i=$1
shift
((i+=1))
done
As an added benefit you can process more than nine (9) positional parameters by using the shift operator.
this sounds right to me ! good one ☝️