Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Bash for loop treat all files at once instead of one after another

I’m facing a weird issue and can’t figure out where its from

I have 2 similar functions :

TMP_DIR="/tmp/folder"
OUTPUT_DIR="output"

func1()
{
   for file in `ls $TMP_DIR/*_INPUT_VLAN.csv`
   do
     local hostname=$(echo $file | awk -F '_INPUT' '{print $1}' | cut -d "/" -f 4)
     OUTPUT=$(echo $hostname"_net_conf.txt")
     IFS=";"
     cat $file | sed '1d' | while read f1 f2 f3 f4 f5 f6 f7 f8
     do
       echo "some things with $f1 $f2 .." >> $OUTPUT_DIR/$OUTPUT
     done
   done
}

func2()
{
   for file in `ls $TMP_DIR/*_INPUT_ROUTES.csv`
   do
     local hostname=$(echo $file | awk -F '_INPUT' '{print $1}' | cut -d "/" -f 4)
     OUTPUT=$(echo $hostname"_net_conf.txt")
     IFS=";"
     cat $file | sed '1d' | while read f1 f2 f3 f4
     do
       echo "some things with $f1 $f2 .." >> $OUTPUT_DIR/$OUTPUT
     done
   done
}

My input files look like this :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

file1 : HOSTNAME1_INPUT_VLAN.csv

int;type;vxid;name;id;ip;mask;comment
int1;int;0;vlan1;1;192.168.1.1;255.255.255.0;VLAN Network 1
int2;ext;1;vlan2;1;192.168.2.1;255.255.255.0;VLAN Network 2
int3;int;2;vlan3;1;192.168.3.1;255.255.255.0;VLAN Network 2

file2 : HOSTNAME2_INPUT_VLAN.csv

int;type;vxid;name;id;ip;mask;comment
int1;int;0;vlan1;1;192.168.1.1;255.255.255.0;VLAN Network 1
int2;ext;1;vlan2;1;192.168.2.1;255.255.255.0;VLAN Network 2
int3;int;2;vlan3;1;192.168.3.1;255.255.255.0;VLAN Network 2

file1 : HOSTNAME1_INPUT_ROUTES.csv

Network;Interface;Gateway;Comment
0.0.0.0/0;int1;gateway1;Comment 1
net_1;int2;gateway2;Comment2
net_2;int2;gateway2;Comment2,1
net_3;int3;gateway3;Comment3

file2 : HOSTNAME2_INPUT_ROUTES.csv

Network;Interface;Gateway;Comment
0.0.0.0/0;int1;gateway1;Comment 1
net_1;int2;gateway2;Comment2
net_2;int2;gateway2;Comment2,1
net_3;int3;gateway3;Comment3

When I run the script, the first function succeed but it looks like the second one is not doing the for loop and try to cat both files at once :

cat: '/tmp/folder/HOSTNAME1_INPUT_ROUTES.csv'$'\n''/tmp/folder/HOSTNAME2_INPUT_ROUTES.csv': No such file or directory

If I had some echos in the functions to see what happens, I see that both files are proceed at the same time

func1()
{
  for file in `ls $TMP_DIR/*_INPUT_VLAN.csv`
  do
    local hostname=$(echo $file | awk -F '_INPUT' '{print $1}' | cut -d "/" -f 4)
    OUTPUT=$(echo $hostname"_net_conf.txt")
    echo "Hostname for $file will be : $hostname"
    echo "Ouput for $file will be located in : $OUTPUT_DIR/$OUTPUT"
  done
}

function2()
{
  for file in `ls $TMP_DIR/*_INPUT_ROUTES.csv`
  do
    local hostname=$(echo $file | awk -F '_INPUT' '{print $1}' | cut -d "/" -f 4)
    OUTPUT=$(echo $hostname"_net_conf.txt")
    echo "Hostname for $file will be : $hostname"
    echo "Ouput for $file will be located in : $OUTPUT_DIR/$OUTPUT"
  done
}

Output :

Hostname for /tmp/folder/HOSTNAME1_INPUT_VLAN.csv will be : HOSTNAME1
Ouput for /tmp/folder/HOSTNAME1_INPUT_VLAN.csv will be located in : output/HOSTNAME1_net_conf.txt

Hostname for /tmp/folder/HOSTNAME1_INPUT_ROUTES.csv
/tmp/folder/HOSTNAME2_INPUT_ROUTES.csv will be : HOSTNAME1
HOSTNAME2
Ouput for /tmp/folder/HOSTNAME1_INPUT_ROUTES.csv
/tmp/folder/HOSTNAME2_INPUT_ROUTES.csv will be located in : output/HOSTNAME1
HOSTNAME2_net_conf.txt

cat: '/tmp/folder/HOSTNAME1_INPUT_ROUTES.csv'$'\n''/tmp/folder/HOSTNAME2_INPUT_ROUTES.csv': No such file or directory

Both functions do the for loop in the same why, I don’t get why the func2 doesn’t proceed as excepted.

I find a workaround by listing files in directory, storing in a tmp file and reading the tmp file with a while loop though, but I wanna know why the original for loop is not not working

Thanks in advance for your help

>Solution :

func1 sets IFS to ; so the output of ls $TMP_DIR/*_INPUT_ROUTES.csv in func2 isn’t being split on newlines anymore. IFS controls how word splitting is performed so you need to be very careful when modifying it.

Some general recommendations:

  for file in "$TMP_DIR"/*_INPUT_VLAN.csv ; do
    ...
  done
  • Try to localize your IFS changes using scoped environment variables or subshells where possible. For example if you just need IFS changed for your while-loop then use this. The change to IFS will be limited to your read command this way.
cat $file | sed '1d' | while IFS=';' read f1 f2 f3 f4 f5 f6 f7 f8
     do
       echo "some things with $f1 $f2 .." >> $OUTPUT_DIR/$OUTPUT
     done
  • Run your script through shellcheck to look for common issues. It will highlight many common issues like the ls parsing problem.
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading