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.
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.
Related
I am trying to split the path of a file to get the directory name to check if the directory exists in the new location or not using shell script.
I tried using
cf=src/classes/CarExperience.cls
echo ${cf%/*}
echo ${cf##/*/}
echo ${cf#/*/*/}
echo ${cf%/*}
echo $(dirname "$cf")
But none of these are giving me desired result
Desired result is get part after the src and check if that inner directory exists or not.
cf=src/classes/CarExperience.cls
directory_name=classes
Appreciate any help on this regard.
You could do:
full_dir=$(dirname "$cf")
last_dir=$(basename "$full_dir")
or in one shot
last_dir=$(basename "$(dirname "$cf")")
Yes, you want all those quotes.
With shell parameter expansion:
full_dir=${cf%/*}
last_dir=${full_dir##*/}
That one has to be done in 2 steps.
Like this, using parameter expansion as you try to do:
cf=src/classes/CarExperience.cls
cf=${cf#src/*} # become 'classes/CarExperience.cls'
echo ${cf%/*} # become 'classes'
Output
classes
I have little scripting experience. I have tried a new script to loop through multiple subdirectories and edit a file if the subdirectory exists. Here is the code I've failed with after multiple attempts, but I cannot resolve the for loop error:
!#/usr/din/sh
for domain in {PGBWAHS_NA PGBWAHS04_NA PGBWAHD_NA PGBWAHD04_NA PGBWAHQ_NA PGBWAHQ02_NA PGBWAHQ03_NA PGBWAHQ04_NA PGBWAHP_NA PGBWAHP02_NA PGBWAHP03_NA PGBWAHP04_NA
do
echo "$domain this is the current domain from the array"
cd /opt/tibco/tra/domain/$domain
echo `pwd` "this is the directory after cd command"
cp hawkagent.cfg hawkagent.cfg.back
sed 's/-scan_rate 10/-scan_rate 30/' hawkagent.cfg
Done
____________________
Error message returned:
$ ./modify_log_scan_rate.sh
./modify_log_scan_rate.sh[3]: Syntax error at line 3 : `for' is not matched.
Remove the opening curly braces after in: for domain in *{*PGBWAHS_NA ...
Done needs to be done (case matters).
– Etan Reisner
I have a groups of files in a folder. Each group is identified by characters 3-6 in the file name. I want to read in all the files of the group, count how many files there are, and then assign the file name to a variable made up of some letters and the counter. e.g. FILENAME$COUNTER. My code is almost working but there seems to be a problem with assigning the counter to the variable name.
I get this error for the line with code FILE$COUNTER=$i
line 12: FILE1=5_lib1ln1_BWA_ddrot_testonl_pe12.bam: command not found
This is exactly what I wanted for the variable name and assignment, but its saying command not found. I'm not sure why there is a command not found.
#!/bin/bash
## All files from the same group have the same LIB
LIB='lib1'
COUNTER=0
for i in 5_*.bam
do
SAMPLIB=`echo $i | cut -c 3-6`
if [ "$LIB" = "$SAMPLIB" ]; then
let COUNTER++
FILE$COUNTER=$i
fi
NUMFILES=$COUNTER
done
Replace
FILE$COUNTER=$i
with
eval FILE$COUNTER=$i
See eval command in Bash and its typical uses for more information.
I have recently just made this script:
if test -s $HOME/koolaid.txt ; then
Billz=$(grep / $HOME/koolaid.txt)
echo $Billz
else
Billz=$HOME/notkoolaid
echo $Billz
fi
if test -d $Billz ; then
echo "Ok"
else touch $Billz
fi
So basically, if the file $HOME/koolaid.txt file does NOT exist, then Billz will be set as $HOME/koolaid.txt. It then sucesfully creates the file.
However, if I do make the koolaid.txt then I get this
mkdir: cannot create directory : No such file or directory
Any help would be appreciated
Here is a difference between content of a variable and evaluated content...
if your variable contains a string $HOME/some - you need expand it to get /home/login/same
One dangerous method is eval.
bin=$(grep / ~/.rm.cfg)
eval rbin=${bin:-$HOME/deleted}
echo "==$rbin=="
Don't eval unless you're absolutely sure what you evaling...
Here are a couple things to fix:
Start your script with a "shebang," such as:
#!/bin/sh
This way the shell will know that you want to run this as a Bourne shell script.
Also, your conditional at the top of the script doesn't handle the case well in which .rm.cfg exists but doesn't contain a slash character anywhere in it. In that case the rbin variable never gets set.
Finally, try adding the line
ls ~
at the top so you can see how the shell is interpreting the tilde character; that might be the problem.
I'm trying to create a file hierarchy to store data. I want to create a folder for each data acquisition session. That folder has five subfolders, which are named below. My code attempt below gives an error, but I'm not sure how to correct it.
Code
#!/bin/sh
TRACES = "/Traces"
LFPS = '/LFPS'
ANALYSIS = '/Analysis'
NOTES = '/Notes'
SPIKES = '/Spikes'
folders=($TRACES $LFPS $ANALYSIS $NOTES $SPIKES)
for folder in "${folders[#]}"
do
mkdir $folder
done
Error
I get an error when declaring the variables. As written above, bash flips the error Command not found. If, instead, I declare the file names as TRACES = $('\Traces'), bash flips the error No such file or directory.
Remove the spaces between the variable names and the values:
#!/bin/sh
TRACES="/Traces"
LFPS='/LFPS'
ANALYSIS='/Analysis'
NOTES='/Notes'
SPIKES='/Spikes'
folders=($TRACES $LFPS $ANALYSIS $NOTES $SPIKES)
for folder in "${folders[#]}"
do
mkdir $folder
done
With spaces, bash interprets this like
COMMAND param1 param2
with = as param1
I'm taking the 'no spaces around the variable assignments' part of the fix as given.
Using array notation seems like overkill. Allowing for possible spaces in names, you can use:
for dir in "$TRACE" "$LFPS" "$NOTES" "$PASS"
do mkdir "$dir"
done
But even that is wasteful:
mkdir "$TRACE" "$LFPS" "$NOTES" "$PASS"
If you're worried that the directories might exist, you can avoid error messages for that with:
mkdir -p "$TRACE" "$LFPS" "$NOTES" "$PASS"
The -p option is also valuable if the paths are longer and some of the intermediate directories might be missing. If you're sure there won't be spaces in the names, the double quotes become optional (but they're safe and cheap, so you might as well use them).
Also you would want to do some checking beforehand if folders exist or not.
Also you can always debug the shell script with set -x, you could just use "mkdir -p" which would do the trick.
I made the following changes to get your script to run.
As a review comment it is unusual to create such folders hanging off the root file system.
#!/bin/sh
TRACES="/Traces"
LFPS='/LFPS'
ANALYSIS='/Analysis'
NOTES='/Notes'
SPIKES='/Spikes'
folders="$TRACES $LFPS $ANALYSIS $NOTES $SPIKES"
for folder in $folders
do
mkdir $folder
done
Spaces were removed from the initial variable assignments and I also simplified the for loop so that it iterated over the words in the folders string.