1

In python, you can

sys.stdout = open('log', 'w') # begin redirect

then output will write to log instead.

You can restore back to normal behavior with

sys.stdout = sys.__stdout__   # end redirect, restore back

How to achieve similar effect in zsh & bash?

P.S.,

  • stdout of command in subshell should also be redirected.
  • ls > log is not what I want.

To clarify, what I want is

ls   # output to terminal
# begin redirect to `log`
ls   # output to `log`
find -type f   # output to `log`
...  # output to `log`
# end redirect, restore back
ls   # output to terminal

Edit Below are not what I want

  • redirection a group of command.
  • tail -f for monitoring.

As The first few lines of this question stated, what I want is

# ...
cmd1    # normal behavior
# begin redirection
cmd2   # redirect to file
# some times later
cmd2   # redirect to file
# ...
cmdN   # redirect to file
# end redirection
cmdN+1 # normal behavior
# ...
qeatzy
  • 1,363
  • 14
  • 21

3 Answers3

3

Typically, you would redirect output for a command group, rather than redirecting and restoring output for the shell itself.

ls                    # to terminal
{
  ls
  find -type f
} > log               # to log
ls                    # to terminal again

Standard output for the command group delimited by { ... } as a whole is redirected to a file. The commands in that group inherit their standard output from the group, not directly from the shell.

This is similar to doing the following in Python:

from contextlib import redirect_stdout

print("listing files to terminal")
with open("log", "w") as f, redirect_stdout(f):
    print("listing files to log")
    print("finding files")
print("listing files to terminal")

In shell, the equivalent of your forced redirection of standard output can be accomplished by using exec, as demonstrated by oguz ismail, though the command group makes it clearer where the redirection begins and ends. (It also avoids needing to find an unused file descriptor and remembering even more arcane shell syntax.)

chepner
  • 497,756
  • 71
  • 530
  • 681
2

You can use the tee command to log to a file as well as print to console:

ls                         # output to terminal
# begin redirect to `log`
ls  | tee -a log           # output to `log`
find -type f | tee -a log  # output to `log`
...  # output to `log`
# end redirect, restore back
ls   # output to terminal
brokenfoot
  • 11,083
  • 10
  • 59
  • 80
2

Permanent redirections are made using exec. For example:

ls              # to tty 
exec 3>&1 >log  # redirect to log, save tty
ls              # to log
find -type f    # ditto
exec >&3        # restore tty
ls              # to tty
oguz ismail
  • 1
  • 16
  • 47
  • 69