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?

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

2 Answers 2

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
4
  • 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, 2015 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). Apr 8, 2015 at 11:48
  • So this wont work if I schedule my script in crontab?
    – Menon
    Apr 9, 2015 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. Apr 9, 2015 at 12:30
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
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .