How to redirect output of a command to a file when the command will prompt user inputs?

By default, only STDOUT is redirected and/or piped. What you want is to leave STDOUT alone, and have whatever is passed via STDIN redirected.

If editing the_command is an option, you could make sure that the question is output to STDERR instead (that should dump it to screen regardless of any redirects), and then have it echo whatever the user types back to screen via STDOUT.


Your command works and properly redirects the output to the file abc.txt.
The question is how is your script asking the input data and how are you running the script?
Let we see with two examples:

# Script_1.sh                                     # 1
echo Please, enter your firstname and lastname    # 2
read FN LN                                        # 3
echo "Hi! $LN, $FN !"                             # 4

and

# Script_2.sh                                     # 5
read -p "Enter a comment " CM                     # 6
echo  "You said $CM"                              # 7

If you run /bin/bash Script1.sh > abc.txt you will not see the question "Please enter..." on your tty. If you will give the expected input from keyboard you will find the output of line #2 and #4 in your abc.txt file.

If you run /bin/bash Script2.sh > abc.txt you will see the question "Enter a comment ", but you will find in the abc.txt file only the output of the line #7.

Note: if you run the Script2,sh in a subshell

(bash Script2.sh 2>&1)> abc.txt

you will not see any output on tty and you will find all in the abc.txt file.
If you run it with

bash Script2.sh 2>ccc.txt 1>ddd.txt`

you will find the Standard output (line #7) in ddd.txt and the standard error (line #6) inccc.txt.


If you want to redirect only part of your command output you have to modify your script.
One of the way to do it, is to create a function in which to move the part of the script that will generate the interesting output (see below). Then you can call this function from the main part of your script (where it was originally the code that you moved into the function) redirecting only that output to the log file:

 Part_To_Redirect(){
     : # all that you want
 }

 # ... Main part of the script
 # point where it was the part that generates the output
 Part_to_Redirect "$@" > abc.txt   # this to store only that part in the file
 # Part_to_Redirect "$@" >> abc.txt  # this to append that part in the file
 # ...

You should even find useful tee that

redirects the output to multiple files, copies standard input to standard output and also to any files given as arguments.

 the_command  | tee abc.txt       # To redirect Standard output
 or 
 the_command 2>&1 | tee abc.txt   # To redirect err in out and both in the file

In this case you will have the normal outputs of your command on the tty, but at the same time you will save a copy in the log file abc.txt. It should be cosy in your case if you use read -p as in the script2 the invocation the_command | tee abc.txt.

Notes and references:

Adding "$@" you can pass all the argument of your script to the function.

You may find interesting to read more about bashredirection from many sources on internet.

  • As suggested by Scott in his comment there is a wiki answer of Unix SE: a good starting point.
  • A must the man bash or the bash manual.
  • I found useful the redirection chapter of bash-hackers where you can find links to obsolete uses too.
  • You can refer to the Advanced Bash-Scripting Guide, chapter 20 too.