TheInnerParty TheInnerParty - 8 months ago 43
Bash Question

Why are stdin and stdout seemingly interchangeable?

I understand that stdin and stdout (at least in UNIX parlance) are stream buffers, and that stdout is used to output from a program to the console (or to then be piped by a shell, etc), and that stdin is for standard input to a program..

So why is it, at least on macOS, that they can be used interchangeably (stdout as stdin, and vice versa?


  1. If you run
    cat /dev/stdin
    then type something in, and it echoes it back. Running the command as
    cat /dev/stdout
    does the same thing.

  2. Similarly,
    echo "Hey There" > /dev/stdout
    echo "Hey There" > /dev/stdin
    both output 'Hey There' back to the terminal.

  3. It also works in C++:


#include <iostream>
#include <string>
#include <fstream>

int main(int argc, const char * argv[]) {
std::string echoString;
std::fstream stdoutFile;"/dev/stdout");
stdoutFile << "Hey look! I'm using stdout properly!\nNow You trying using it wrongly: " << std::endl;
stdoutFile >> echoString;
stdoutFile << "You Typed: " << echoString << std::endl;

When prompted, typing a single word, followed by EOF (Ctrl+D) works as expected.

Answer Source

Because, typically, when a program is invoked from an interactive terminal, with no redirection, both standard input and standard output are connected to the same terminal device, such as /dev/tty (the actual device name varies based on the operating system).

The terminal device is a read/write device. Reading from the terminal device reads terminal input. Writing to the terminal device generates output on the terminal.

You still have discrete file descriptors, 0 and 1, but they're connected to the same device.

Think of it as single, bi-directional pipe, that's duped to both file descriptors 0 and 1.

Linux behaves the same way (you can echo Foo >/dev/stdin and see the output):

$ ls -al /proc/self/fd/[01]
lrwx------. 1 mrsam mrsam 64 Nov 22 21:34 /proc/self/fd/0 -> /dev/pts/1
lrwx------. 1 mrsam mrsam 64 Nov 22 21:34 /proc/self/fd/1 -> /dev/pts/1

So, for this process, file descriptors 0 and 1 is connected to the /dev/pts/1, the same pseudo-terminal device. Whether you are reading from file descriptor 0 or file descriptor 1, you end up reading from the same underlying /dev device, so it makes no difference which actual file descriptor you use.

This is, of course, operating system-dependent. Other POSIX-based operating systems may implement their standard input and output in other ways, where you can't actually write to standard input and read from standard output.