1

I am reading a file and redirecting the entire output to a file. I would like to redirect stdout and stderr of certain expressions to the screen as shown below (just an example):

#!/bin/bash
OLDIFS=$IFS
while IFS='|'
while read fname fpath dname dpath ; do
echo "$fname" >> redirect to screen
echo "$fpath"
echo "$dpath"
diff "$fpath/$fname" "$dpath/$dname" >> redirect to screen
done > logfile

I tried >$(tty) but that didn't work. This didn't work either:

while read fname fpath dname dpath; do
echo "$fname" >&1
echo "$fpath"
echo "$dname"
echo "$dpath"
diff "$fpath/$fname" "$dpath/$dname" >&1
done > logfile

I can't use tee because it redirects the entire output to screen. How can I achieve this?

  • You could do that using awk. – Manuel Faux Apr 7 '15 at 9:23
  • The question is why tty doesn't work. What does a call to tty in terminal print out? – FloHimself Apr 7 '15 at 9:28
2

Your while loop is non-interactive, thus doesn't have a tty. You have to save your tty device before entering the loop. So you'd have something like:

my_tty=$(tty)

while read fname fpath dname dpath ; do
  echo "$fname" | tee ${my_tty}
  echo "$fpath"
  echo "$dpath"
  diff "$fpath/$fname" "$dpath/$dname" | tee ${my_tty}
done > logfile
3
while …; do
  echo "$fname" >&1
done > logfile

The standard output of the echo command is redirected to its standard output. In other words, >&1 is a no-op. The 1 in >&1 designates file descriptor 1 of the command where it is used, not of some mysteriously-chosen outer scope.

To redirect to a file that is available at an outer scope, duplicate the file descriptor in that outer scope, and don't redirect the duplicated file descriptor.

while read fname fpath dname dpath; do
  echo "$fname" >&3
  echo "$fpath"
  echo "$dname"
  echo "$dpath"
  diff "$fpath/$fname" "$dpath/$dname" >&3
done 3>&1 >logfile

Note the order of the redirections on the loop: first create a file descriptor 3 that goes where file descriptor 1 (standard output) is currently going, then redirect file descriptor 1 somewhere else.

Alternatively, you could open the log file on a different descriptor.

while read fname fpath dname dpath; do
  echo "$fname"
  echo "$fpath" >&3
  echo "$dname" >&3
  echo "$dpath" >&3
  diff "$fpath/$fname" "$dpath/$dname"
done 3>logfile
  • Thanks for the information. This really helped me since I am new to scripting. But, what should I do if I want to redirect a particular expression only to screen and not to file? – Menon Apr 8 '15 at 11:15
  • @Menon That's my first example: save the screen in a file descriptor (3 in my example) and use that for a particular instruction. Keep in mind that your script's output can itself be redirected, so this won't always be the terminal (there might not be a terminal at all, e.g. in a daemon or scheduled task). – Gilles Apr 8 '15 at 11:48
  • So this wont work if I schedule my script in crontab? – Menon Apr 9 '15 at 6:04
  • @Menon If you redirect to the screen, this won't work in a crontab. But none of the examples I give redirect to the screen, and my point is that in general you shouldn't redirect to the screen. – Gilles Apr 9 '15 at 12:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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