You seem to be mixing bash and gnuplot in a strange way. Using a bash script to try to generate a gnuplot script on the fly with inserted variables is a quick way to confuse yourself. It also makes it difficult to read and debug. It is easy to forget what bash is evaluating and what gnuplot is evaluating.
When I look at your first line
ArrLength=${#arr[@]} #Get the length of array
I can see that this is bash code because gnuplot would interpret a comment beginning with the first #
. (This is also bash's syntax for arrays, not gnuplot's.) The dollar sign $
has a different meaning in gnuplot. Rather than mark a variable identifier, $
is a column number operator ($2
is column 2, $i
is column i, etc.). So look at the line
plot for [p=0:$ArrLength] "$outputdir/${arr[$p]}/values.csv" using 1:2 with lines title "${arr[$p]}"
This is clearly a line of bash syntax, apparently inside a string trying to write a line of gnuplot. Bash will evaluate the variables $ArrLength
, $outputdir
, and ${arr[$p]}
, and replace them with some string of their values. Also keep in mind that p
is a variable in gnuplot, not a variable in bash. Bash will evaluate $p
to something (an empty string if it has not been defined). You can't expect the gnuplot variable p
to be used as the index in the bash evaluation of ${arr[$p]}
, and then somehow result in a different string for each iteration of gnuplot's loop.
In short, what you have written is not gnuplot syntax, and it is really not a minimal and complete bash script either. It is not clear exactly how you intended bash and gnuplot to fit together like this, but it seems you have joined them too tightly.
My suggestion is to write a bash script and write a gnuplot script (as separate files). Gnuplot has its own flow control, iteration loops, and variable evaluation. You can write a self-contained gnuplot script for the general case of everything you need it to do, and then give it specifics on the command line from your bash script.
For example, it seems that your subdirectories are all multiples of 10, and always starting with 10. The only variable aspect is how many there are (what the last one is). Let's say this last value was somehow stored in a gnuplot variable last
. Also, suppose we also somehow have the base output directory in outputdir
:
(Inside the gnuplot script, named plot.gp
):
plot for [p=10:last:10] sprintf("%s/%d/values.csv", outputdir, p) with lines title sprintf("%d", p)
The for [p=10:last:10]
means to iterate from 10 through last
(inclusive), adding 10 at each iteration. The first sprintf()
function (like C) builds a string with the outputdir
and p
(both are variables in gnuplot). The using 1:2
is not necessary as the first two columns are the default columns to use with lines
, but you can include them if you want to be explicit. The second sprintf()
builds a title string from the iteration variable p
.
Now, this assumes that outputdir
and last
have meaningful values. You can assign these values from your bash script when you invoke gnuplot on the command line:
(Inside the bash script, invoke the gnuplot script)
gnuplot -e "last=40" -e "outputdir=\"$outputdir\"" plot.gp
The -e
option tells gnuplot to evaluate the given string before running the script in the file plot.gp
. In this example, the gnuplot variable last
will have the value 40 and the gnuplot variable outputdir
will have whatever value bash evaluates $outputdir
to be. Notice the escaped double quotes inside double quotes. The outer double quotes are to allow bash to evaluate variables inside the string ($outputdir
needs to be evaluated by bash). The inner (escaped) quotes are to delimit the string within the gnuplot code. For example, if bash evaluates $outputdir
to data
, then gnuplot would see outputdir="data"
which is a valid gnuplot assignment of a string to the variable outputdir
. You could, if you want, combine these two -e
options into one:
gnuplot -e "last=40;outputdir=\"$outputdir\"" plot.gp
You will likely want to use the value for last
from your array in bash, rather than hard coding it like this. So in practice it may look more like
gnuplot -e "last=${arr[${#arr[@]}-1]};outputdir=\"$outputdir\"" plot.gp
Or, if you have bash 4.3 or later, you should be able to use a negative index:
gnuplot -e "last=${arr[-1]};outputdir=\"$outputdir\"" plot.gp
Notice that there are no escaped quotes around the use of the array variable. It is expected that it will evaluate to an integer (40
, 90
, etc.) and we want to assign last
to an integer, not a string like outputdir
.
If this one string seems complex, try thinking about the entire script like this. It would be easy to get confused as to what bash is doing and what gnuplot is doing.
In summary, write a bash script, and a separate gnuplot script. Gnuplot is capable of handling a general case. From bash, just give it some specifics on the fly, don't try to generate the entire script on the fly. It really does make things simpler.