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

5,530

Solution 1

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.

Solution 2

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.

Solution 3

There are usually 2 important output pipes: STDOUT (for regular output) and STDERR (for error messages).

The problem here is, that the "regular" output of the command and the text of the prompt are both written to STDOUT, so they are always put into the same location. When you use your redirection, it just takes the whole STDOUT, including the prompt.

If rewriting (as suggested in another answer by Jarmund) of the command is not possible, maybe the command has an additional option/flag (like --output), that can specify some output file instead of using the redirection?

Share:
5,530

Related videos on Youtube

Aaron Shen
Author by

Aaron Shen

Updated on September 18, 2022

Comments

  • Aaron Shen
    Aaron Shen almost 2 years

    I have a command which will prompt user for some inputs and then output the result to the terminal. I typed the command like below to redirect the output to a file:

    $the_command > abc.txt
    

    But it doesn't work. The problem is there's no prompt, those prompt questions' text is output to the abc.txt not the result I want.

  • glglgl
    glglgl about 9 years
    STDERR should dump it to screen regardless of any redirects No. If you redirect 2>xyz, stderr is redirected as well. But a program can open and use /dev/tty which uses the controlling terminal regardless of any redirections.
  • Scott - Слава Україні
    Scott - Слава Україні about 9 years
    I believe that What are the shell's control and redirection operators? is a better reference.
  • Hastur
    Hastur about 9 years
    @Scott, precious as usual. There are so many sources on internet that nowadays it is difficult to select just one that fit your needs, especially when you do not know the person (I mean the OP).
  • Scott - Слава Україні
    Scott - Слава Україні about 9 years
    Well, the point is that I pointed you to our reference.  Also, I needed only to glance at your two to find inaccuracies and sloppy writing.  ("precious as usual"?)
  • Joker_vD
    Joker_vD about 9 years
    @glglgl I've seen a couple of programs that insisted on working with /dev/tty/ directly, and they were pretty annoying. They don't take input STDIN, they continue to pollute your terminal, and they're very surprised when they happen to run without a terminal.
  • Hastur
    Hastur about 9 years
    @Scott: what didn't you like precious or usual? We meet here 2 times in few days and both your comments helped me to do a better answer... and this made you, without any offence, "precious as usual". :-)
  • Scott - Слава Україні
    Scott - Слава Україні about 9 years
    OK; "precious" struck me as being snide, but I guess that's a tertiary meaning.