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. Commented Apr 7, 2015 at 9:23
  • The question is why tty doesn't work. What does a call to tty in terminal print out? Commented 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? Commented 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). Commented Apr 8, 2015 at 11:48
  • So this wont work if I schedule my script in crontab? Commented 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. Commented 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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.