0

I have a bash script that I need to run for a series of files. The script takes 4 arguments. The first ref is a file, fun is a directory, R1arr and R2arr each are arrays containing a series of files with specific features in a given directory.

My script.sh is as follows:

ref="$1"
fun=$2
R1arr="$@"
R2arr="$@"

analyseReads -i "$ref" -o "$fun" --left "${R1arr[@]}" --right "${R2arr[@]}"

And I run it for various files as follows:

FORWARD=($(for i in Sample_STE*/*R1; do echo $i; done))
REVERSE=($(for i in Sample_STE*/*R2; do echo $i; done))

bash script.sh "$ref" "$fun" "${FORWARD[@]}" "${REVERSE[@]}"

I get an error since "${FORWARD[@]}" and "${REVERSE[@]}" does not only contain the files in the array FORWARD and REVERSE but it also contains "$ref" and "$fun". Why does this happen and how could I solve this issue?

Homap
  • 2,142
  • 5
  • 24
  • 34
  • 2
    At the operating-system level, an argument list on UNIX is a single array of NUL-delimited C strings. When you expand an array, each string it contains becomes a separate argument; the callee has no way of knowing where each individual array began and ended. – Charles Duffy Oct 15 '19 at 21:05
  • 1
    ...that said, the way you're assigning your arrays is buggy in the first place. It'd need to be `FORWARD=( Sample_STE*/*R1 )` to not mangle the lists before you even try to do anything else with them. – Charles Duffy Oct 15 '19 at 21:06
  • 1
    `R1arr="$@"` is inherently buggy too; when you assign an array to a string variable, information about where the original boundaries were is lost. – Charles Duffy Oct 15 '19 at 21:08
  • 1
    [BashPitfalls #50](http://mywiki.wooledge.org/BashPitfalls#hosts.3D.28_.24.28aws_....29_.29) is useful background on the side issue mentioned in my second comment. And [BashPitfalls #14](http://mywiki.wooledge.org/BashPitfalls#echo_.24foo) explains a *separate* reason why the original code is broken. – Charles Duffy Oct 15 '19 at 21:09
  • 1
    The first of the two approaches given in my answer on the linked duplicate https://stackoverflow.com/questions/34905635/passing-multiple-arrays-as-a-parameter-in-bash will work for you; the second (pass-by-reference) one only works when calling shell functions, not calling external scripts. – Charles Duffy Oct 15 '19 at 21:12
  • Thanks a lot! From your answer on passing multiple arrays, could you please explain what does this section mean=? `array1=( "${@:2:$1}" ); shift "$(( $1 + 1 ))"` Thank you! – Homap Oct 15 '19 at 21:40
  • 1
    `shift` removes things from the front of the argument list (so `shift 1` or just `shift` changes `$2` to `$1`, `$3` to `$2`, etc). `"${array[@]:start:len}` expands to `len` values from position `start` in `array`. – Charles Duffy Oct 15 '19 at 21:49
  • 1
    See https://wiki.bash-hackers.org/syntax/pe as a general intro to parameter expansion in shell (of which the array expansion above is a subset), https://wiki.bash-hackers.org/syntax/expansion/arith re: arithmetic expansion, and https://wiki.bash-hackers.org/commands/builtin/shift re: `shift`. – Charles Duffy Oct 15 '19 at 21:51

0 Answers0