A pipeline is just a shell convenience which attaches the stdout
of one process directly to the stdin
of the next:
There are a lot of subtleties to how this works, for example, the stderr
stream might not be piped as you would expect, as shown below:
I have spent quite some time trying to write a detailed but beginner friendly explanation of pipelines in Bash. The full content is at:
https://effective-shell.com/part-2-core-skills/thinking-in-pipelines/
Every standard process in Unix has at least three file descriptors, which are sort of like interfaces:
The pipe connects the standard output of the process to the left to the standard input of the process of the right. You can think of it as a dedicated program that takes care of copying everything that one program prints, and feeding it to the next program (the one after the pipe symbol). It's not exactly that, but it's an adequate enough analogy.
Each pipe operates on exactly two things: the standard output coming from its left and the input stream expected at its right. Each of those could be attached to a single process or another bit of the pipeline, which is the case in a multi-pipe command line. But that's not relevant to the actual operation of the pipe; each pipe does its own.
The redirection operator (>
) does something related, but simpler: by default it sends the standard output of a process directly to a file. As you can see it's not the opposite of a pipe, but actually complementary. The opposite of >
is unsurprisingly <
, which takes the content of a file and sends it to the standard input of a process (think of it as a program that reads a file byte by byte and types it in a process for you).
A pipe takes the output of a process, by output I mean the standard output (stdout
on UNIX) and passes it on the standard input (stdin)
of another process. It is not the opposite of the simple right redirection >
which purpose is to redirect an output to another output.
For example, take the echo command on Linux which is simply printing a string passed in parameter on the standard output. If you use a simple redirect like :
echo "Hello world" > helloworld.txt
the shell will redirect the normal output initially intended to be on stdout and print it directly into the file helloworld.txt
.
Now, take this example which involves the pipe :
ls -l | grep helloworld.txt
The standard output of the ls
command will be outputed at the entry of grep, so how does this work?
Programs such as grep
when they're being used without any arguments are simply reading and waiting for something to be passed on their standard input (stdin)
. When they catch something, like the ouput of the ls command, grep acts normally by finding an occurence of what you're searching for.
Pipes are very simple like this.
You have the output of one command. You can provide this output as the input into another command using pipe. You can pipe as many commands as you want.
ex:ls | grep my | grep files
This first lists the files in the working directory. This output is checked by the grep command for the word "my". The output of this is now into the second grep command which finally searches for the word "files". Thats it.
The pipe operator takes the output of the first command, and 'pipes' it to the second one by connecting stdin and stdout. In your example, instead of the output of dmesg command going to stdout (and throwing it out on the console), it is going right into your next command.
|
puts the STDOUT of the command at left side to the STDIN of the command of right side.
If you use multiple pipes, it's just a chain of pipes. First commands output is set to second commands input. Second commands output is set to next commands input. An so on.
It's available in all Linux/widows based command interpreter.
All of these answere are great. Something that I would just like to mention, is that a pipe in bash (which has the same concept as a unix/linux, or windows named pipe) is just like a pipe in real life.If you think of the program before the pipe as a source of water, the pipe as a water pipe, and the program after the pipe as something that uses the water (with the program output as water), then you pretty much understand how pipes work.And remember that all apps in a pipeline run in parallel.
Regarding the efficiency issue of pipe:
If you treat each unix command as a standalone module,
but you need them to talk to each other using text as a consistent interface,
how can it be done?
cmd input outputecho "foobar" string "foobar" cat "somefile.txt" file *string inside the file*grep "pattern" "a.txt" pattern, input file *matched string*
You can say |
is a metaphor for passing the baton in a relay marathon.
Its even shaped like one!cat -> echo -> less -> awk -> perl
is analogous to cat | echo | less | awk | perl
.
cat "somefile.txt" | echo
cat
pass its output for echo
to use.
What happens when there is more than one input?cat "somefile.txt" | grep "pattern"
There is an implicit rule that says "pass it as input file rather than pattern" for grep
.
You will slowly develop the eye for knowing which parameter is which by experience.