11

There are two ways of reading a file line by line that I want to discuss here:

#!/bin/bash    

while read line    
do    
    echo-e "$ line \ n"    
done <file.txt

and

#!/bin/bash    
exec 3<file.txt

while read line    
do    
    echo-e "$ line \ n"    
done

So first version works fine but I don't understand the mechanism of working while loop with the file. But the mechanism of the second version I understand. But here I don't understand why it hangs and does not print anything.

4 Answers 4

9

The first loop works because the redirection after the done applies to the whole loop, so the read there is reading from the file, not from the standard input of the script.

The second version hangs because read reads from file descriptor 0, which is standard input, and you've not typed anything there. The exec line redirects file descriptor 3 for reading from the file, but you're not reading from file descriptor 3.

You could rescue the second by using:

exec <file.txt

Now standard input is read from the named file.

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

Comments

4

This might work for you:

exec 3<file.txt

while read -u3 line
do
    echo -e "$line \n"
done

-u3 reads from file descriptor 3

Strange that echo does not have the complement switch like ksh's print command.

Comments

3

There are few mistakes in your scripts.

  1. Space between $ and variable name. (may be bad edit)
  2. Space between echo and -e. (may be bad edit)
  3. Mentioning the read at a file descriptor where the file is open. You are reading the file at descriptor 0 and exec is running at descriptor 3.

It should be something like this -

#!/bin/bash    
exec 3<file.txt

while read line  
do
    echo -e "$line \n"
done <&3

4 Comments

Does <&3 on the read line work? It used to be the case, back in the bad old days of the real Bourne shell, that the redirection would be done each time round the loop, so you got funny effects (like the file being closed on each iteration). I can well believe it has been modified since then so that things work a little more sanely. FWIW: when I tried bash on MacOS X, with: while read line < somefile; do echo $line; done, I got the first line of somefile echoed repeatedly...but with the <&3 notation, I did get the successive lines of the file. Be careful!
Thanks Jon, I tried with the above script, it worked on my mac. cl.ly/ClDf but thats some useful info. Ill remember it. I am still very much new to bash. Have just been learning awk and sed. But will start some books on bash basics. :)
Have edited the answer to have <&3 after done statement instead of read statement.
This works fine on Mac OS/X, don't forget the quotes: while read line; do echo $line; done <"somefile"
0

-u3 is great for my purpose (reading only the following line)

#!/bin/bash

logs=(*Logs.txt)
[[ -e "${logs[0]}" ]] || exit 0

exec 3<"${logs[0]}"

while read -u3 line
do
        if [[ $(echo "$line"| grep -c SCSI_STATUS_CHECK_CONDITION) -eq 1 ]]; then
                read -u3 line
                echo "$line"
        fi
done

Comments

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.