How to redirect output of an entire shell script within the script itself? How to redirect output of an entire shell script within the script itself? shell shell

How to redirect output of an entire shell script within the script itself?


Addressing the question as updated.

#...part of script without redirection...{    #...part of script with redirection...} > file1 2>file2 # ...and others as appropriate...#...residue of script without redirection...

The braces '{ ... }' provide a unit of I/O redirection. The braces must appear where a command could appear - simplistically, at the start of a line or after a semi-colon. (Yes, that can be made more precise; if you want to quibble, let me know.)

You are right that you can preserve the original stdout and stderr with the redirections you showed, but it is usually simpler for the people who have to maintain the script later to understand what's going on if you scope the redirected code as shown above.

The relevant sections of the Bash manual are Grouping Commands and I/O Redirection. The relevant sections of the POSIX shell specification are Compound Commands and I/O Redirection. Bash has some extra notations, but is otherwise similar to the POSIX shell specification.


Typically we would place one of these at or near the top of the script. Scripts that parse their command lines would do the redirection after parsing.

Send stdout to a file

exec > file

with stderr

exec > file                                                                      exec 2>&1

append both stdout and stderr to file

exec >> fileexec 2>&1

As Jonathan Leffler mentioned in his comment:

exec has two separate jobs. The first one is to replace the currently executing shell (script) with a new program. The other is changing the I/O redirections in the current shell. This is distinguished by having no argument to exec.


You can make the whole script a function like this:

main_function() {  do_things_here}

then at the end of the script have this:

if [ -z $TERM ]; then  # if not run via terminal, log everything into a log file  main_function 2>&1 >> /var/log/my_uber_script.logelse  # run via terminal, only output to screen  main_functionfi

Alternatively, you may log everything into logfile each run and still output it to stdout by simply doing:

# log everything, but also output to stdoutmain_function 2>&1 | tee -a /var/log/my_uber_script.log