IO Redirection

Programming Workshop 2 (CSCI 1061U)

Faisal Qureshi

Faculty of Science, UOIT

http://vclab.science.uoit.ca


Unix Bash Shell allows I/O redirection via <, >> and > commands. Redirection allows us to send output from a file, command, program, or script to another file, command, program, or script. In Unix the following three files are always open:

Redirecting stdout to a file

Use commands > and >>.

Command >

output  > filename

Truncates file "filename" to zero-length; if file doesn't exist, create a zero-length file. All stdout commands, such as printf, cout, etc. will write to the file "filename". Here output refers to any output from a file, command, program, or script.

Example

ls > directory-listing.txt

Command >>

output >> filename

Creates a zero-legnth file if one doesn't already exist. If a file exists, contents will be appended to it. All stdout commands, such as printf, cout, etc. will write to the file "filename". Here output refers to any output from a file, command, program, or script.

Example

ls > directory-listing.txt; ls >> directory-listing.txt

Other uses

Using :

: > filename

: is a dummy placeholder that produces no output. The effect of this command is similar to touch filename.

Example

: > foo.txt

Single-line IO redirections

These are often used within scripts to send single line outputs to a file.

1> filename

Sends stdout to filename. Similarly use 1>>.

2> filename

Sends stderr to filename. Similarly use 2>>.

&> filename

Sends both stdout and stderr to filename. Similarly use &>>.

File descriptors

We can use <> to open a file for reading and writing and assign a file descriptor to it

echo newton > foo.txt
exec 7<> foo.txt

File descriptor 7 now points to file foo.txt.

Cases M>N and M>&N

M>N

Output from file descriptor M goes to filename N.

M>&N

Output from file descriptor M goes to file descriptor N.

Examples
2>&1

Redirects stderr to stdout, i.e., error messages are also sent out to stdout.

i>&j

Redirects output of file descriptor i to file descriptor j.

>&j 

All output to stdout will no go to file descriptor j.

Redirecting file contents to stdin

Command <

program < filename

Contents in the file are provided to stdin functions (scanf, cin, etc.) in the program.

Consider the following program (prog.cpp).

#include <iostream>
using namespace std;

int main()
{
    int n;
    char c;

    cout << "Enter an integer: ";
    cin >> n;
    cout << "Enter a char: ";
    cin >> c;
    
    cout << "integer is " << n << " and character is " << c << endl;
    
    return 0;
}

Assume we have the following file (input.txt)

232 r

When we execute the program as follows, the output is:

$ g++ prog.cpp -o prog
$ ./prog < input.txt
Enter an integer: 
Enter a char:
integer is 232 and character is r
$

Notice that the user didn't have to enter an integer or a character. Despite the fact that these items needed to be entered via stdin--since cin was used to read it. Instead the < command tied file "input.txt" to the stdin. Consequently, cin in the program took the required values (an integer and a character) from this file.

This is a great way to automate program testing. Since user doesn't have to respond to any prompts from the program.

Commandline arguments

Note that ./prog < input.txt doesn't mean that < and input.txt are passed as command line arguments. If the intention is to pass these items as command line arguments then use the following command ./prog \< input.txt. The backslash character \ is the escape character that we use to tell the Bash shell that < should be treated as a character and not as a means to redirect a file to stdin.

Using Unix pipe (|) command

This is a general purpose command chaining tool. It is similar to >.

cat notes.txt | my-prog > output.txt

Command cat reads the contents of notes.txt file and sends these to my-prog. The output of my-prog is sent to the output.txt file.

Using IO redirection for automatic testing

Consider the following piece of code that sums two numbers and prints the result.

#include <iostream>

using namespace std;

int main()
{
    int a, b;
    cin >> a >> b;
    cout << a+b;
    return;
}

We can test this program by executing it and entering two numbers. The program prints the output and if the output is what we expect, we assume that the program is correct. We can automate this process as follows:

Step 1

Create an input file

input1.txt

2 4

Step 2

Create an output file

output1.txt

6

The output file contains the correct answer.

Step 3

Execute the program as follows

> ./sum < input.txt > program-output.txt

Step 4

Now compare the output of the program with the expected output.

> diff output1.txt program-output.txt

If diff commands returns nothing, all is well. Otherwise there is an issue that needs attention.

References