1

I am trying to create directories whose names are variables defined in an array. When I run my code below I do not understand the errors

#!/bin/bash
#
Output_Base_Dirs=(/home/user/CORDEX/OUTPUT/historical /home/user/CORDEX/OUTPUT/rcp45)
Input_Base_Dirs=(/home/user/CORDEX/INPUT/historical /home/user/CORDEX/INPUT/rcp45)
Input_Data_Dirs=(CLMcom-CCLM4-8-17_v1/CNRM-CERFACS-CNRM-CM5_r1i1p1/day/native)

Var_Dirs=(precip tmin tmax)
Vars=(pr tasmin tasmax)

# Create directories called by the variable name, if not there
###########################################################
for i in "${Output_Base_Dirs[@]}"
do
   echo $Var_Dirs[i]
   #  if [ ! -d ${Var_Dirs[i]} ]; then
   echo $Var_Dirs[i]
   echo "Directory doesn't exist. Creating now"
   mkdir "$Output_Base_Dirs[i]/$Var_Dirs[i]"
   echo "File created"
#  else
#   echo "Directory exists"
#  fi
done
 exit 0

When I run the above code with the if construct in place I get an error at the line of the if, as follows

precip[i]
./merge_files.sh: line 55: /home/user/CORDEX/OUTPUT/historical: syntax error: operand expected (error token is "/home/user/CORDEX/OUTPUT/historical")

When I run the code with the if construct commented out, I get the following precip[i]

Directory doesn't exist. Creating now
mkdir: cannot create directory ‘/home/user/CORDEX/OUTPUT/historical[i]/precip[i]’: No such file or directory
File created

precip[i]
Directory doesn't exist. Creating now
mkdir: cannot create directory ‘/home/user/CORDEX/OUTPUT/historical[i]/precip[i]’: No such file or directory
File created

Why does

echo $Var_Dirs[i]

print "precip[i]"?

I will appreciate to understand what is the problem and how to do it properly.

4
  • Forgot to mention that this was run on cygwin, but ubuntu 18.04 gives the same errors. Commented Sep 13, 2019 at 9:45
  • Oh boy, you're using values in Output_Base_Dirs as indexes for Var_Dirs Commented Sep 16, 2019 at 5:00
  • There is this thing called "GNU Bash Manual", you should check it out, it's really interesting! Commented Sep 18, 2019 at 23:15
  • I think I close this with the following comments: 1) Sorry I have had no internet connection for some days; 2) It is now my understanding that shell scriting has limited programming capabilities. I have done the same work with a lot of ease in perl. My perl script was not taking a unix command, which is why I tried bash; 3) I did not use values in $Output_Base_Dirs as indices. The index used was [i] (check the loop). The system itself was taking values from $Output_Base_Dirs as indices. The same result was ogt on cygwin and in linux ubuntu; 4) Thank you all who looked at this. Commented Sep 22, 2019 at 18:30

1 Answer 1

1

Quoting from Bash Reference Manual § 6.7 Arrays;

Any element of an array may be referenced using ${name[subscript]}. The braces are required to avoid conflicts with pathname expansion.

...

Referencing an array variable without a subscript is equivalent to referencing the array with a subscript of 0.

That means,

$Var_Dirs[i]

is the same as

${Var_Dirs[0]}[i]

, thus history[i], precip[i], etc. in the output.

The correct syntax is:

${Var_Dirs[i]}

But,

fixing it won't make your script work. Because "${Output_Base_Dirs[@]}" expands to the values in array Output_Base_Dirs, and you're using them as indexes.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks @ismail. I have tried "${Var_Dirs[i]}", ${Var_Dirs[i]}, $Var_Dirs[i] and "$Var_Dirs[i]", I still get the same error in every case tried.
The same combinations have been tried, quoted with curly brackets, without, unquoted with without. Why is it printing precip[i]? I am concluding there is no solution to my problem, maybe it is my platform which is not ok. thanks for your time.
$Output_Base_Dirs[i] was also tried with all combinations as with Var_Dirs[i] in my earlier comment, same result. I am wondering why echo ${Var_Dirs[i]} prints precip[i] instead of evaluating at i=0.
"which bash" gives "/usr/bin/bash"
@ismail thanks for suggesting starting from a simple construction. Indeed the code you provided works and prints "foo". I went a step further and introduced a for loop as follows: foo=(foo1 foo2); for i in "${foo[@]}" ; do; printf "%s\t%s\n" "$i", "${foo[i]}"; done. My system is strange, the output I get is: line 1 - foo1, foo1. line2- foo2, foo1. This is on cygwin. I will send you what I get on linux ubuntu in due course. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.