10

I stored the following program in new.c

int main() 
{ 
    a;
    return 0; 
}

It returns an error message. I want to send this message to a file. So I used the following command

gcc new.c > temp.txt

But still I was getting the output on the terminal. I am using Ubuntu 13.04. How can I make it work?

1

3 Answers 3

17

When you compile a program with gcc, there are different kinds of output: to stdout and stderr. Normally, the > will direct stdout stream to a file (for example, the result of a printf("hello world\n"); is sent to stdout). However, the stderrcontinues to be sent to the screen, since it's assumed to be "something exceptional that you need to be told about".

There is a way to redirect stderr to a file - you do this with the following (not very intuitive) command:

gcc new.c &> myFile

where &> is "bash shorthand" for "redirect everything". As was pointed out by @CharlesDuffy, the POSIX compliant form is

gcc new.c > myFile 2>&1

This means "compile 'new.c' and send stdout to myFile. And send stderr (2) to the same place as stdout (&1 = "the same place as stdout").

You will find more details on different redirects at http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-3.html and http://mywiki.wooledge.org/BashFAQ/055

By the way, if you want to send something from within your program specifically to stderr, you can do so with the following

fprintf(stderr, "hello world - this is urgent.\n");

If you include that in a program, run the program and send the "normal" output to a file, this will still appear on the console. So if you compile the above into the executable urgent, then type

./urgent > /dev/null

at the console, your output will appear on screen.

2
  • 3
    mywiki.wooledge.org/BashFAQ/055 is probably a better introduction to redirection. Also, one really should introduce the POSIX-compliant form (>myFile 2>&1) as well as the bash extension (&>). Jun 22, 2013 at 13:34
  • @CharlesDuffy - both very good points. I will include them in my answer for completeness.
    – Floris
    Jun 22, 2013 at 13:38
11

Because > redirects only stdout, and errors are written to stderr, you need to use one of the following instead:

gcc new.c &> temp.txt ## redirect both stdout and stderr using bash or zsh only

...or...

gcc new.c >temp.txt 2>&1 ## redirect both stdout and stderr in any POSIX shell

&> is a BASH extension which redirects both stdout and stderr to a file; otherwise, the easiest approach is to first redirect stdout (>temp.txt), and then make stderr (FD 2) a copy of the already-redirected file handle on stdout (FD 1), like so: 2>&1.

0
4

As the others have said, linux provides two different output streams:

stdout, or "standard output" is where all regular output goes.
              You can reference it using file descriptor 1.

stderr, or "standard error" is a separate stream for out-of-band information.
              You can reference it using file descriptor 2.

Why two different output streams? Consider a pipeline of imaginary commands:

 decrypt $MY_FILE | grep "secret" | sort > secrets.txt

Now imagine the decrypt command fails and generates an error message. If it sent that message to stdout, it would send into the pipe, and unless it had the word "secret" you'd never see it. So you'd end up with an empty output file, with no idea what went wrong.

However, since the pipe only captures stdout, the decrypt command can send its errors to stderr, where they'll be displayed on the console.

You can redirect stdout and stderr, either together or independently:

# Send errors to "errors.txt" and output to "secrets.txt"
# The following two lines are equivalent, as ">" means "1>"
decrypt $MY_FILE 2> errors.txt > secrets.txt
decrypt $MY_FILE 2> errors.txt 1> secrets.txt

You can redirect the errors to stdout and process them as if they were normal output:

# The operation "2>&1" means "redirect file descriptor 2 to file
# descriptor 1. So this sends all output from stderr to stdout.
# Note that the order of redirection is important.
decrypt $MY_FILE > errors.txt 2>&1 

# This may be confusing.  It will store the normal output in a file
# and send error messages to stdout, where they'll be captured by 
# the pipe and then sorted.
decrypt $MY_FILE 2>&1 > output.txt | sort

You can also use a "shorthand" notation to redirect both stdout and stderr to the same file:

decrypt $MY_FILE &> output.txt

And, finally, the > operator will first truncate its output file before writing to it. If, instead, you want to append data to an existing file, use the >> operator:

decrypt $MY_FILE 2>> more_errors.txt >> more_secrets.txt
decrypt $MY_FILE >> more_output.txt 2>&1
4
  • 1
    Two quibbles: (1) Use of unquoted parameter expansions ($FOO) is a common source of bugs, and demonstrating it in examples is not so great. (2) Use of all-uppercase variable names is the primary reason for namespace conflicts between environment and built-in variables (uppercase by convention) and local variables (lowercase by convention). (3) Encouraging people to repeatedly use >> (which reopens the file every time it's used in a command) rather than opening a file once and leaving the file descriptor open for use by multiple commands results in inefficient code. Jun 22, 2013 at 14:41
  • ...on the last point, compare to: exec 4>secrets; echo "this is a secret" >&4; echo "this is another secret" >&4 Jun 22, 2013 at 14:41
  • +1 Thanks for keeping me honest, @CharlesDuffy. All good points. I intentionally omitted exec for simplicity, though in practice it's generally a better strategy.
    – Adam Liss
    Jun 22, 2013 at 16:59
  • Also, command₁ > output_file ; command₂ >> the_same_output_file can be collapsed to ( command₁ ; command₂ )  > output_file or { command₁ ; command₂ ;  }  > output_file (where there must be spaces before and after the {, and a ; before the }). Feb 3, 2016 at 19:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .