5

I have a text file named sqlfile, with the following content:

a.sql
b.sql
c.sql
d.sql

What I want is that to store them in variables and then print using for loop. But here I get only d.sql in the output of the script.

The script:

#!/bin/bash

while read line
do
files=`echo $line`
done < /home/abdul_old/Desktop/My_Shell_Script/sqlfile

for file in $files
        do
                echo $file
        done
Nick Volynkin
  • 14,023
  • 6
  • 43
  • 67
Abdul Manaf
  • 4,768
  • 3
  • 27
  • 34

6 Answers6

6

A variable can only hold one element, what you want is an array

#!/bin/bash

while read line
do
  files+=( "$line" )
done < /home/abdul_old/Desktop/My_Shell_Script/sqlfile

for file in "${files[@]}"
do
  echo "$file"
done
SiegeX
  • 135,741
  • 24
  • 144
  • 154
5
while read line
do files="$files $line"
done < /home/abdul_old/Desktop/My_Shell_Script/sqlfile

or

files=$(</home/abdul_old/Desktop/My_Shell_Script/sqlfile)

or

files=$(cat /home/abdul_old/Desktop/My_Shell_Script/sqlfile)

You're doing way too much work in your loop.

The middle alternative works with bash; the other two work with most shells. Prefer $(...) to back-quotes.

This code assumes there are no spaces in file names to mess things up. If you do use blanks in file names, you have to work marginally harder - see the array-based solution by SiegeX

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0

Using read is fine but you have to set the IFS environment variable first else leading and trailing white space are removed from each line: Preserving leading white space while reading>>writing a file line by line in bash.

Community
  • 1
  • 1
John
  • 1,671
  • 2
  • 13
  • 14
0

All you have to do is:

readarray myData < sqlfile

This will put file lines into an array called myData
Now you can access any of these lines like this:

printf "%s\n" "${myData[0]}" #outputs first line
printf "%s\n" "${myData[2]}" #outputs third line

And you can iterate over it:

for curLine in "${myData[@]}"; do
    echo "$curLine"
done

Note that these lines would contain \n character as well. To remove trailing newlines you can use -t flag like this:

readarray -t myData < sqlfile

readarray is a synonym to mapfile. You can read about it in man bash

Aleks-Daniel Jakimenko-A.
  • 10,335
  • 3
  • 41
  • 39
0

I think you need to make the "files" as array. otherwise, as soon as the while finishes, "files" stores the latest "line". try:

files=( "${files[@]}" $line )
Dan
  • 10,531
  • 2
  • 36
  • 55
hhwangcocora
  • 65
  • 1
  • 5
0

That's right, you assifn last value to "files"

You must use for instance += instead of =

#!/bin/bash

while read line
do
files+=`echo " $line"`
done < /home/abdul_old/Desktop/My_Shell_Script/sqlfile

for file in $files
        do
                echo $file
        done
Odobenus Rosmarus
  • 5,870
  • 2
  • 18
  • 21
  • You don't need the first `echo`; you could perfectly well use `files+=" $line"` and it would be simpler and more efficient (no subshell). – Jonathan Leffler Jan 16 '12 at 06:49
  • @AbdulManaf: are you using `bash`? Which version of `bash` (find out with `bash --version`). – Jonathan Leffler Jan 16 '12 at 06:49
  • GNU bash, version 4.1.5(1)-release (i686-pc-linux-gnu) – Abdul Manaf Jan 16 '12 at 07:26
  • I use GNU bash, version 4.2.10(1)-release (x86_64-pc-linux-gnu), and += works for me. But the point is -- you must not reassign the variable. You need to add new value. If += doesn't work for you , you can try for instance files="$files $line" – Odobenus Rosmarus Jan 17 '12 at 15:04