I was just playing around in the terminal and I did this:
printf 'some string\n' | {
tee /dev/fd/3 | {
: && sed 's/some/string/'
}
} 3>&0
I was really surprised when I was met with a screen full of:
string string
string string
string string
...
It went on pretty much forever. I pared it down some, and to better demonstrate, maybe try this:
echo | tee /dev/fd/0 | sed =
For me, it presents output like:
<num>
#blank
<num+1>
#blank
...
And so on. The few times I've tried it by the time I could hit CTRL+C I was at line 200k+. I tried this in bash
, dash
, sh
, and zsh
and all present the same results.
What is going on there? How are the file-descriptors passing over that |pipe
between, what I thought were, separate processes? Is this reliable and/or expected behavior? Are there other ways to generate this effect?
For reference:
echo '#blank' | {
uname -r
readlink -f /dev/fd/0
tee /dev/fd/0
} | sed '=;5q'
OUTPUT
1
3.14.6-1-ARCH
2
/proc/24925/fd/pipe:[5851017]
3
#blank
4
#blank
5
#blank
Best Answer
/dev/fd/0
is the current process's standard input;tee
writes its input to both to the file(s) you give it and to stdout. Sotee
is reading a (blank) line, then writing that line to both stdout (sed
) and its own input, where it reads the line it just wrote, writes it to stdout and its own input, etc., creating an infinite loop of (empty) lines*. Thesed
command just prints the line number and then the line.* When provided more input than just a simple
echo
, this command will loop over the input, repeating it over and over.Note: OSX (BSD) doesn't let you write to
/dev/fd/0
, so you can't do this.