HOWTO · C

How to Use File Redirection in C

Learn how to use the shell operators <, >, and >> to redirect a C program's standard input and output. See how shell redirection differs from C stream operations such as fopen and freopen, with examples and error-handling guidance.

On this page

To redirect a C program’s input or output from the command line, use the shell operators <, >, and >>. The shell connects the program’s standard streams to files; C code can instead open a named file with fopen, or change a standard stream with freopen. These are related ways to handle data, but they are different operations.

Understanding File Redirection in C

A C process starts with three standard streams: stdin for input, stdout for normal output, and stderr for diagnostics. A shell normally connects them to the terminal. Redirection changes those connections when it starts the program, so the program can keep calling fgets, printf, or fprintf(stderr, ...) without knowing whether a stream goes to a terminal or a file.

By contrast, fopen returns a separate FILE * that your code reads or writes directly. Use it when the program must choose among files, handle several files at once, or control their lifetimes. Use shell redirection for a run whose input or output destination should be chosen by the caller.

Redirecting Program Output with > and »

This small program writes one line to stdout:

Run this example:

#include <stdio.h>

int main(void) {
    puts("Report complete");
    return 0;
}

The program’s line goes to stdout; this example is not accompanied by a runtime transcript. After compiling it as report, run it with ./report > report.txt to create or replace report.txt. Use ./report >> report.txt to append instead. The > operator truncates an existing destination before the program starts, while >> writes at its end. Shell syntax and available compiler commands vary by platform.

The shell handles opening the redirected destination. If that open fails, the shell reports the problem and ordinarily does not start the program. The program cannot detect this as an fopen failure because it did not open the destination itself. To save diagnostics separately, use ./report > report.txt 2> errors.txt; 2> redirects the conventional file descriptor used for stderr.

Redirecting Program Input with <

Read from stdin when the caller should choose the input source. This program reads lines until the redirected file reaches end-of-file:

#include <stdio.h>

int main(void) {
    char line[128];

    while (fgets(line, sizeof line, stdin) != NULL) {
        if (fputs(line, stdout) == EOF) {
            perror("writing stdout");
            return 1;
        }
    }

    if (ferror(stdin)) {
        perror("reading stdin");
        return 1;
    }
    return 0;
}

Compile it as copy-input, then run ./copy-input < input.txt. fgets reads at most one fewer characters than the buffer capacity, adds a terminating null character, and keeps a newline if it reads one. A long line may therefore be returned in multiple pieces. Check ferror after the loop to distinguish a read failure from normal end-of-file. The example’s behavior follows the C stream operations shown; no observed output is supplied here.

Redirecting Standard Streams Within a C Program

When the program itself must choose a destination, freopen can reopen a standard stream. It takes a path, a mode such as "w" or "a", and the stream to reopen. For example, freopen("run.log", "a", stdout) directs subsequent standard output to append to run.log. Check its return value before writing: it returns NULL if reopening fails. This changes the process stream, unlike fopen, which gives you another stream while leaving stdout alone.

Use this option when redirection is part of the program’s own behavior. If the caller should decide the destination, leave stdout unchanged and use > or >>. freopen is standard C, but details of reopening a stream after a failure can depend on the implementation; handle a NULL result and do not continue as though redirection succeeded.

Handle Errors and Choose the Right Approach

Check every operation that can fail. Test fopen and freopen before using their returned stream, check output functions such as fprintf or fputs for failure, and check fclose when it matters that buffered output reached the file. For input loops, a NULL result from fgets can mean end-of-file or a read error; inspect ferror to tell them apart. perror can report an operating-system message for a failure associated with the current errno.

Do not size a line buffer from a file’s reported byte length: input can be a pipe or terminal, and a line may be longer than the chosen buffer. A fixed buffer with repeated fgets calls is suitable when processing chunks is acceptable. For an arbitrarily long logical line, grow a buffer as chunks arrive and check allocation and arithmetic limits, or use a platform-specific line-reading facility with its portability limits stated.

Choose shell redirection to connect a run’s standard streams, fopen to manage an additional file in C, and freopen when the program needs to replace a standard stream itself. Keep diagnostics on stderr when normal output is redirected, and check failures at the layer that performs the operation.