Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

My bash script (lets call it myscript) takes input either from stdin (pipe), or form a regular file (if filename was provided as an argument)

a) someprog | myscript

   or

b) myscript file.txt

Then, the data is processed line by line. At the moment, my code looks something like the following:

if [ -t 0 ] ; then
    while read LINE
      do
         prog_1
         prog_2
         ...
         prog_n
      done
else
    while read LINE
      do
         prog_1
         prog_2
         ...
         prog_n
      done < $1
fi

This script works fine, but there seems to be too much duplicity. I am wondering whether there is a better (more elegant) way to do it. All the steps 1 to n are the same. The only difference is whether there is a < $1 at the end or not. is there no better way to do it?

share|improve this question

3 Answers 3

up vote 5 down vote accepted

Functions are the general way to reduce code duplication. This case isn't any different. You just need to to define a function to implement your while read logic.

myfunc() {
    while read LINE
    do
        prog_1
        prog_2
        ...
        prog_n
    done
}

if [[ -t 0 ]]; then
    myfunc # read stdin passed to the script
else
    myfunc < "$1" # redirect file to stdin
fi
share|improve this answer

I usually use

cat "$@" | while read line ; do
    ...
done

The only problem might be if someone calls someprog | myscript file.txt (but the same problem exists in the original code).

share|improve this answer

If an argument is given, redirect stdin from it then reuse the code.

if [ -t 0 ]; then
    exec 3<&0
elif (( $# > 0 )) && [[ -r $1 ]]; then
    exec 3<"$1"
else
    echo no stdin and no file to read
    exit 1
fi

while IFS= read -r -u 3 LINE; do
     prog_1
     prog_2
     ...
     prog_n
done

exec 3<&-
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.