Question: I'd wish the user to `select` a file from a numbered list on screen in a `mkinitcpio` `busybox` `ash` environment. The list needs to be filled/sorted from top to bottom and printed in columns, like:

```
1) 2017-12-17   3) 2017-12-19   5) 2017-12-21   7) 2017-12-23  9) 2017-12-25
2) 2017-12-18   4) 2017-12-20   6) 2017-12-22   8) 2017-12-24

```

I am printing to screen using `printf` line by line. That is why you would normally use an array. Because `busybox` `ash` lacks array support the hack is to use `set` to create a poor man's array using positional parameters (`$1=2017-12-17`, `$2=2017-12-18`, etc.).

For now I manage to retrieve the positional parameter value using:

```
file=$(eval echo \$$i)

```

Is there a better way to retrieve the **n-th positional parameter** in **ash**?

---

Notes

1. The column listing above is a simplified example, the actual file names do contain time stamps too, like for example `2017-12-27-060056`.
2. [Mkinitcpio busybox 1.27.2 compile config](https://git.archlinux.org/svntogit/packages.git/tree/trunk/config?h=packages/mkinitcpio-busybox).

Answer: 
Use:

```
eval "file=\${$i}"

```

No need for command substitution which mangles data as it strips trailing newlines and is inefficient as it involves a fork() and a pipe() and shoving the data between two processes through that pipe.

`echo` should also not be used for arbitrary data.

Also note the braces that are needed in the POSIX sh syntax for numbers above 9.

If `$i` is read from the user, you may want to make sure it's a decimal integer from 1 to `$#` without leading `0`s or `+`s first to avoid command injection vulnerabilities:

```
valid() { # args: string min max
  case $1 in
    (*[!0123456789]* | 0* | "" | ??????????*) return 1
  esac
  [ "$1" -ge "$2" ] && [ "$1" -le "$3" ] 
}

until
  printf>&2 'Enter number: '
  IFS= read -r number
  valid "$number" 1 "$#"
do
  echo>&2 "Not a valid number. Please try again."
done
eval "file=\${$number}"

```
You can use shift. It's better than eval.

cat busy.sh

```
leshift () {
  shift "$1"
  echo "$1"
}
echo param debut
echo $#
echo $@
for i in "$@" ; do
  echo "$i"
done

echo param shift
read a # number from 1 to 5
b=$(leshift "$a" "$@")
echo $b

echo param fin
echo $#
echo $@
for i in "$@" ; do
  echo "$i"
done

```

You call it like that

```
./busy.sh a b 'c h' d e

```