You have a significant number of basic errors in your script. Before posting on StackOverflow, you will always want to use ShellCheck to fix all basic errors.
While you generally do not use hand-written sorting routines in shell programming (utilities like sort are used), for a learning exercise there is nothing wrong with doing so. As mentioned in the comments, to fill an array from the lines of an input file, use readarray or use mapfile (both are equivalent). For example if providing the filename as the first argument to your script, you can fill array from the filename given (or read from stdin by default) using:
infile="${1:-/dev/stdin}" ## set filename or read from stdin
[ -r "$infile" ] || { ## validate file readable
printf "error: invalid filename.\n" >&2
exit 1
}
readarray -t array < "$infile" ## readarray from file
By using $(seq "${#elements[@]}") you are creating an indexing nightmare. In bash valid array indexes are from 0 -> n-1, however by using $(seq "${#elements[@]}") you are providing numbers 1 -> n (which you will have to subtract 1 from to map to valid indexes. Instead you are better served by using a C-style for loop and staying with indexes from the array itself with, for example:
for ((i = 0; i < ${#elements[@]}; i++)); do
...
done
Next, as noted above in the comments your attempted comparison with [ ${elements[k]} > $key ] fails because within [ ... ] the > operates as a redirection instead of a comparison. If you are using the arithmetic operator ((....)) for the test, then > provides the greater-than comparison.
Finally, if you are going to the trouble of writing an insertion sort for an array in bash, you may as well make it a function so it is reusable. The only caveat there is bash doesn't provide a direct mechanism for passing an array to a function. (which is another reason you generally do not find hand-rolled sorting functions in bash)
You can however, for the purpose of this learning exercise, expand the array (e.g. "${elements[@]}" ) and then capture the elements in a local array within the function for sorting and then output the elements for reading back into the original array. For example, you could write an inssort() function taking advantage of that similar to:
## inssort() expects expanded array as positional parameters
# outputs sorted array to stdout
inssort() {
[ $# -gt 1 ] || { ## validate at least 2 arguments given
printf "error: cannot sort single value.\n" >&2
return 1
}
local arr=( "$@" ) ## local array to insert values in sort order
local n=${#arr[@]} ## local values to use in sort
local i=0
local j=0
local tmp=0
## insertion sort arr
for ((i = 0; i < n; i++)); do
for ((j = i-1; j >= 0; j--)); do
if (( ${arr[j]} > ${arr[$((j+1))]} )); then
tmp=${arr[j]}
arr[j]=${arr[$((j+1))]}
arr[$((j+1))]=$tmp
else
break
fi
done
done
echo "${arr[@]}" ## output sorted array
}
An then back in your script your could call and capture the results similar to:
array=( $(inssort "${array[@]}") ) ## insertion sort array
I can't impress on you enough, for sorting in an actual shell script, rely on the utilities that have been written to handle sorting, like sort. But for completion of this example, you could put your script together similar to the following:
#!/bin/bash
## inssort() expects expanded array as positional parameters
# outputs sorted array to stdout
inssort() {
[ $# -gt 1 ] || { ## validate at least 2 arguments given
printf "error: cannot sort single value.\n" >&2
return 1
}
local arr=( "$@" ) ## local array to insert values in sort order
local n=${#arr[@]} ## local values to use in sort
local i=0
local j=0
local tmp=0
## insertion sort arr
for ((i = 0; i < n; i++)); do
for ((j = i-1; j >= 0; j--)); do
if (( ${arr[j]} > ${arr[$((j+1))]} )); then
tmp=${arr[j]}
arr[j]=${arr[$((j+1))]}
arr[$((j+1))]=$tmp
else
break
fi
done
done
echo "${arr[@]}" ## output sorted array
}
infile="${1:-/dev/stdin}" ## set filename or read from stdin
[ -r "$infile" ] || { ## validate file readable
printf "error: invalid filename.\n" >&2
exit 1
}
readarray -t array < "$infile" ## readarray from file
echo "array : ${array[*]}" ## output original array
array=( $(inssort "${array[@]}") ) ## insertion sort array
echo "sorted : ${array[*]}" ## output sorted array
Then you can either pass input to the script on stdin or provide a filename to read the array elements from, e.g.
Example Input File
$ cat dat/20int.txt
91
-72
5
-33
-60
-54
95
13
62
1
70
-3
68
-99
89
77
100
8
31
-43
Example Use/Output
$ bash inssortarr.sh dat/20int.txt
array : 91 -72 5 -33 -60 -54 95 13 62 1 70 -3 68 -99 89 77 100 8 31 -43
sorted : -99 -72 -60 -54 -43 -33 -3 1 5 8 13 31 62 68 70 77 89 91 95 100
Look things over and let me know if you have questions, then after you have finished your exercise, rely on the shell utility sort to handle your sorting needs. It will be much faster and much less error-prone...
forandcattogether like this; see Bash FAQ 001.