Stdin, Stdout, Stderr explained

Acronyms

| Acronym | Meaning | | ------- | ------------ | | I/O | Input/Output | | std | Standard | | in | Input | | out | Output | | err | Error |


Data streams

Computer processns have diferent data streams.

Data streams are used to communicate with the user and other processs.

There are input data streams and output data streams.

Input data streams

Input data streams are used to get data from the user or other processs:

  • stdin

Output data streams

Output data streams are used to send data to the user or other processs:

  • stdout
  • stderr

Error data streams

Output data streams are also used to send error messages to the user or other processs:

  • stderr

Shell

$ echo "Hello World"

When we run the above command in the shell, all our data streams are directly connected to the terminal.

This means that the input is read from the keyboard and the output is displayed on the screen.


Redirection

By default, all data streams are connected to the terminal.

This means that the input is read from the keyboard and the output is displayed on the screen.

But these are just the default connections.

We can change the connections between the process and the data streams however we want.

Changing the connections between the process and the data streams is called redirection.

We can redirect all data streams or just some of them.


Output redirection

$ echo "Hello World" > hello.txt

When we run the above command in the shell, the input is still read from the keyboard.

But the terminal is no longer connected to the output data stream of the process.

Instead the output data stream is connected to the file hello.txt.

The output is no longer displayed on the screen. It is written to the connected file.


Input redirection

$ cat < hello.txt

When we run the above command in the shell, the output is still displayed on the screen.

But the terminal is no longer connected to the input data stream of the process.

Instead the input data stream is connected to the file hello.txt.

The input is no longer read from the keyboard. It is read from the connected file.


Pipe

$ echo "Hello World" | cat

We can connect the output data stream of one process to the input data stream of another process.

This is called a pipe.

The whole command is called a pipeline.

We can have as many pipes as we want.

Each pipe connects the output data stream of one process to the input data stream of the next process.


File descriptors

File descriptors are used to identify data streams.

| File descriptor | Data stream | | --------------- | ----------- | | 0 | stdin | | 1 | stdout | | 2 | stderr |


Differentiate output streams

When redirecting data streams, we can use the file descriptors to differentiate the output streams.

1 is the file descriptor for the normal output stream.

$ echo "Hello World" 1> hello.txt

The normal output stream is the default ouptut stream.

So we can omit the file descriptor:

$ echo "Hello World" > hello.txt

2 is the file descriptor for the error output stream.

$ echo "Hello World" 2> error.txt

Individual files

Redirect both output streams into individual files in one command:

$ echo "Hello World" 1> hello.txt 2> error.txt

Same file

Redirect both output streams into the same file in one command:

$ echo "Hello World" &> hello.txt

Detecting redirection

processs can detect if their data streams are connected to a terminal.

This can be used to conditionally display output.

For example, we may want to display text differently if the output is redirected to a file and not displayed on the screen.


In bash scripts, we can use the [[ -t FD ]] condition to detect if a file descriptor is connected to a terminal.

FD is the file descriptor.


Detecting input redirection

#!/bin/bash

if [[ -t 0 ]]; then
  echo "stdin via terminal"
else
  echo "stdin via file or pipe"
fi

The first condition is true when the input stream is comming from the terminal directly:

$ ./script.sh

The second condition is true when the input stream is comming from a file:

$ ./script.sh < hello.txt

Or from a pipe:

$ echo "Hello World" | ./script.sh

Detecting output redirection

#!/bin/bash

if [[ -t 1 ]]; then
  echo "stdout via terminal"
else
  echo "stdout via file or pipe"
fi

The first condition is true when the output stream is comming from the terminal directly:

$ ./script.sh

The second condition is true when the output stream is going into a file:

$ ./script.sh > hello.txt

Or into a pipe:

$ ./script.sh | cat

Examples from other languages

Node.js

process.stdin.on("data", (data) => {
  process.stdout.write(data.toString().toUpperCase())
})

Python

import sys

for line in sys.stdin:
  sys.stdout.write(line.upper())

PHP

<?php

while ($line = fgets(STDIN)) {
  fwrite(STDOUT, strtoupper($line));
}

background scene
Join the garden
Finally enjoy quality-first content.
'cause low-quality sucks

legal privacy