Pipe is used to pass output to another program or utility.
Redirect is used to pass output to either a file or stream.
Example: thing1 > thing2
vs thing1 | thing2
thing1 > thing2
- Your shell will run the program named
thing1
- Everything that
thing1
outputs will be placed in a file called thing2
. (Note - if thing2
exists, it will be overwritten)
If you want to pass the output from program thing1
to a program called thing2
, you could do the following:
thing1 > temp_file && thing2 < temp_file
which would
- run program named
thing1
- save the output into a file named
temp_file
- run program named
thing2
, pretending that the person at the keyboard typed the contents of temp_file
as the input.
However, that's clunky, so they made pipes as a simpler way to do that. thing1 | thing2
does the same thing as thing1 > temp_file && thing2 < temp_file
EDIT to provide more details to question in comment:
If >
tried to be both "pass to program" and "write to file", it could cause problems in both directions.
First example: You are trying to write to a file. There already exists a file with that name that you wish to overwrite. However, the file is executable. Presumably, it would try to execute this file, passing the input. You'd have to do something like write the output to a new filename, then rename the file.
Second example: As Florian Diesch pointed out, what if there's another command elsewhere in the system with the same name (that is in the execute path). If you intended to make a file with that name in your current folder, you'd be stuck.
Thirdly: if you mis-type a command, it wouldn't warn you that the command doesn't exist. Right now, if you type ls | gerp log.txt
it will tell you bash: gerp: command not found
. If >
meant both, it would simply create a new file for you (then warn it doesn't know what to do with log.txt
).
The script probably knows which shell it should be running in. The first line might be something like
#!/bin/bash
If you run it with sh
, the first line (a.k.a. shebang) is ignored. A different shell tries to run the script, but does not understand it - it is like running Java code in Pascal. If you run it with the right shell, it should behave identically:
/bin/bash script.sh
Best Answer
"When to use" is really dependant on you're doing. It's like asking when to use a Phillips or a slothead screwdriver. I can tell you what they all are, and what they do, but working out when you'd use each one, is up to you.
All of these are extensively documented in the TLDP Advanced Bash Scripting Guide. If you need examples, that's the place.
< filename
reads from a file into STDIN> filename
writes STDOUT to file, overwriting anything.>> filename
writes STDOUT to file, appending if it already exists.<(command)
absorbs the output of the internal command and provides a filename>(command)
provides a filename to the outer command but actually redirects anything written to it to the STDIN of the internalcommand
.<<TOKEN
is a here document, aka heredoc. It'll read anything that follows into STDIN until it seesTOKEN
again. It's useful for multi-line content. It has to be followed by a newline. Unless you quote the token, heredocs support variable substitution.<<-TOKEN
is as above except that it will ignore leading tabs (but only tabs). This is handy to preserve source formatting but it really does only work with tabs. It's rendered useless on Stack Exchange sites because they substitute tabs for spaces :(<<"TOKEN"
is a heredoc that won't substitute$variables
.<<<"string"
is a herestring. It's read into STDIN. This can do variable substitution.| command
joins the current STDOUT to the STDIN ofcommand
|& command
joins STDOUT and STDERR onto the STDIN ofcommand
(useful for grepping error output)1>
and2>
are used to explicitly redirect STDOUT and STDERR.>
implies1>
so you rarely see it used explicitly.>&1
and>&2
can be used to redirect into STDOUT and STDIN./dev/std{in,out,err}
also exist as symlinks to the basic in/out/error file descriptors. This is dead handy when something will only accept a filename argument but you want it to write to STDOUT, for example.