Here is how we normally do shell redirection
$ ./pgm.sh args >out.txt 2>err.txt
I wanted to modify it a bit and run as follows
$ ./pgm.sh args
with the requirement that output and error should go to some filename computed inside pgm.sh based on args. One illustrative case could be when date is part of args. So you would like stdout to go to say /your/directory/pgm_out_YYYYMMDD.txt 1
The problem with standard way of redirecting
N>file.txt i.e, associating file descriptor N to file.txt , is that it works only for the newly forked process and not for the current process.
$ echo hi 1>out.txt ; echo hii will send hi to out.txt but will print hii to stdout.2
This is where
exec comes to our rescue. If we add
exec 1>somefile.txt then output from rest of the script will go to somefile.txt
$./test.sh will redirect hi as well as hii to out.txt
$ cat test.sh
Similarly to redirect stdout as well as stderr we’ll do something like this
echo out text
echo 1>&2 err text
ls -ld /tmp
Now coming back to original point of redirecting to some file from inside the shell, let’s say program computed the filename in some variable OUTFILE, we could have just done
That solves the current problem. But you may like to go through following example which achieves ‘random access’ of file in shell script. Example is from here
echo 1234567890 > File # Write string to "File".
exec 3<> File # Open "File" and assign fd 3 to it.
read -n 4 <&3 # Read only 4 characters.
echo -n . >&3 # Write a decimal point there.
exec 3>&- # Close fd 3.
cat File # ==> 1234.67890
With comments, this code is self explanatory.
1 It can also be done by
$ ./pgm.sh args >pgm_out`date +%Y%m%d` but idea is to generate this file name based on some logic in program itself.
2 1 in 1>out.txt is redundant but it clarifies here that we are redirecting fd 1