how to differentiate error returned while reading and for EOF in shell script

By : Anu

I have this task of uploading a delimited file and processing it. Once the processing is done, i either say its successful and if parsing fails, i need to throw the error. I'm reading this file line by line in child script and then processing it in main script (so i cant use ifs while read).

Im renaming to .done in case all lines are parsed. Now i would like to know when there is an error before EOF has reached so that i can rename it to .err. And what if i have a file without newline character at the end?

Structure is mostly as below:

Main script:
Calls parent script with filepath
gets the fileName and no of line in the files, calls the Child script with a nth line no in a loop until total no of lines are reached

Parent script:
#some validations to get the txt file from the list of files
fileName=`ls -A1 *.txt`

Child script:
line=`tail -$lineno $fileName | head -n1`

if [ $lineno -eq $noOfLines ] 
    mv "$fileName" "$noExt.done" #success case

Now i also need to rename the file to .err if its erroneous or parsing fails. Pls let me know how do i catch the error.

By : Anu

In shell, you read with read, not by iterating over the lines with head and tail. That being said, the POSIX standard states, in its description:


  The following exit values shall be returned:
       Successful completion.
       End-of-file was detected or an error occurred.

This means that you cannot distinguish between EOF and error on reading in shell.

As for the other subquestion, there are good reasons why files must have a trailing newline; I’ve seen sed(1) either not act on, or even strip, the last line if it did not have one, on some unixoid system.

By : mirabilos

You can use exit 1 or exit 0 in your child script (use 0 for "no error"), and check the return value $? in the parent script. When you want to see the exit code of your tail command, this solution fails: $? will be the exitcode of the head -n1. In ksh you can't use the Bash solution ${PIPESTATUS}. The best way to handle this is replacing the tail..head construction by a single command (sed ${lineno}'q;d' "${filename}").

Your example code is not complete, I do not see why you need to get one line for each call. For a large file this is quite some overhead. Please think it over!

By : Walter A

This video can help you solving your question :)
By: admin