DavidC.
DavidC.

Reputation: 677

Nested for loops in bash

In the directory from where I am running a bash script,

directory saved in the variable:

ScriptDir=`pwd`

I have the following files:

B3LYP_BOTTOM_FRAGMENT
B3LYP-D3_BOTTOM_FRAGMENT
PBE_BOTTOM_FRAGMENT
LDA_BOTTOM_FRAGMENT
PBE-D3_BOTTOM_FRAGMENT
PBE0_BOTTOM_FRAGMENT
PBE0-DC_BOTTOM_FRAGMENT

254.186305_TOP_FRAGMENT.d12
252.050453_TOP_FRAGMENT.d12
249.921810_TOP_FRAGMENT.d12
247.812353_TOP_FRAGMENT.d12
245.699603_TOP_FRAGMENT.d12
243.644688_TOP_FRAGMENT.d12
241.581529_TOP_FRAGMENT.d12
239.554134_TOP_FRAGMENT.d12
237.467646_TOP_FRAGMENT.d12
235.473555_TOP_FRAGMENT.d12

These files can be classified into two different variables: DIRS and FOLDERS

DIRS="
PBE-D3
PBE
B3LYP
B3LYP-D3
PBE0
PBE0-DC
LDA
"
FOLDERS="
237.467646
239.554134
241.581529
243.644688
245.699603
247.812353
249.921810
252.050453
254.186305
235.473555
"

Given this path: /path/to/target, If I loop over DIRS ($i) and FOLDERS ($j), I would like to end up with the following:

ls -lrth /path/to/target/PBE-D3/scaling_volumes/237.467646

237.467646_TOP_FRAGMENT.d12          #   j = 1 on FOLDERS 
PBE-D3_BOTTOM_FRAGMENT               #   i = 1 on DIRS
237.467646.d12

# where `237.467646.d12` is the result of doing:
# cat 237.467646_TOP_FRAGMENT.d12 PBE-D3_BOTTOM_FRAGMENT  >  237.467646.d12

ls -lrth /path/to/target/PBE-D3/scaling_volumes/239.554134

239.554134_TOP_FRAGMENT.d12          #   j = 2 on FOLDERS
PBE-D3_BOTTOM_FRAGMENT               #   i = 1 on DIRS
239.554134.d12

ls -lrth /path/to/target/PBE-D3/scaling_volumes/241.581529

241.581529_TOP_FRAGMENT.d12          #   j = 3 on FOLDERS
PBE-D3_BOTTOM_FRAGMENT               #   i = 1 on DIRS
241.581529.d12

# and so on... 
# In other words, in this iteration, all the `j`th `FOLDERS` for a given `j`th `DIR`

# For the second `DIR`, again the 1st `FOLDER`:
ls -lrth /path/to/target/PBE/scaling_volumes/237.467646

237.467646_TOP_FRAGMENT.d12          #   j = 1 on FOLDERS
PBE_BOTTOM_FRAGMENT                  #   i = 2 on DIRS 
237.467646.d12  

# and so on

I have written the following script:

DIRS="
PBE-D3
PBE
B3LYP
B3LYP-D3
PBE0
PBE0-DC
LDA
"
FOLDERS="
237.467646
239.554134
241.581529
243.644688
245.699603
247.812353
249.921810
252.050453
254.186305
235.473555
"

ScriptDir=`pwd`

for i in ${DIRS}; do

 cd /path/to/target/$i

 rm -Rf scaling_volumes
 mkdir scaling_volumes

 cd scaling_volumes

 for j in ${FOLDERS}; do
  rm -Rf ${j}
  mkdir ${j}
  cd  $ScriptDir

  cp -avr  ${j}_TOP_FRAGMENT.d12  /path/to/target/$i/scaling_volumes/${j}

  cp -avr ${i}_BOTTOM_FRAGMENT /path/to/target/$i/scaling_volumes/${j}

  cd /path/to/target/$i/scaling_volumes/${j}

  cat ${j}_TOP_FRAGMENT.d12 ${i}_BOTTOM_FRAGMENT > ${j}.d12

  cd  $ScriptDir

  done

done

For some reason what I receive is:

ls -lrth /path/to/target/PBE-D3/scaling_volumes

235.473555   # Only the last FOLDER has been created

or:

ls -lrth /path/to/target/PBE/scaling_volumes

235.473555   # Only the last FOLDER has been created

where only last jth FOLDER was created

Upvotes: 0

Views: 897

Answers (2)

DavidC.
DavidC.

Reputation: 677

Following @choroba 's great advice, I managed to solve the problem by creating a

scaling=`pwd` 

variable, and place it just before the for j in ${FOLDERS} loop, and end this loop with

cd  $scaling

However, I am very interested in the || exit 1 approach suggested by @Nahuel Fouilleul but I am afraid I do not know where to start with.

ScriptDir=`pwd`

for i in ${DIRS}; do

 cd /home/david/Trabajo/structures/Trial_for_double_for_loop_in_bash/pob_TZVP/Calcite_I/$i

 rm -Rf scaling_volumes_from_117.743646
 mkdir scaling_volumes_from_117.743646

 cd scaling_volumes_from_117.743646

 scaling=`pwd`

 for j in ${FOLDERS}; do
  rm -Rf ${j}
  mkdir ${j}
  cd  $ScriptDir

  cp -avr  ${j}_TOP_FRAGMENT.d12  /home/david/Trabajo/structures/Trial_for_double_for_loop_in_bash/pob_TZVP/Calcite_I/$i/scaling_volumes_from_117.743646/${j}

  cp -avr ${i}_BOTTOM_FRAGMENT /home/david/Trabajo/structures/Trial_for_double_for_loop_in_bash/pob_TZVP/Calcite_I/$i/scaling_volumes_from_117.743646/${j}

  cd /home/david/Trabajo/structures/Trial_for_double_for_loop_in_bash/pob_TZVP/Calcite_I/$i/scaling_volumes_from_117.743646/${j}

  cat ${j}_TOP_FRAGMENT.d12 ${i}_BOTTOM_FRAGMENT > ${j}.d12

  cd  $scaling

  done

done

Upvotes: 0

Nahuel Fouilleul
Nahuel Fouilleul

Reputation: 19315

  • Fail fast, add || exit 1 after cd and mkdir commands
  • Avoid cd use it only when necessary because paths are absolute

Also script directory can be different from pwd (current working directory), for example if script is called from another directory.

Upvotes: 1

Related Questions