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).

Thank you. You mentioned thing1 > temp_file && thing2 < temp_file to do more easier with pipes. But why not re-use the > operator to do this, e.g. thing1 > thing2 for commands thing1 and thing2 ? Why an extra operator | ?
–
John ThreepwoodAug 7 '12 at 13:57

1

"Take the output and write it to a file" is a different action than "Take the output and pass it to a different program". I'll edit more thoughts into my answer...
–
David OneillAug 7 '12 at 14:01

1

@JohnThreepwood They have different meanings. What if I wanted to redirect something to a file named less, for example? thing | less and thing > less are perfectly different, as they do different things. What you propose would create an ambiguity.
–
DarkhoggMay 25 '14 at 9:55

Is it accurate to say that "thing1 > temp_file" is merely syntactic sugar for "thing1 | tee temp_file" ? Since finding out about tee I almost never use redirects.
–
Sridhar-SarnobatJun 5 '14 at 5:09

@Sridhar-Sarnobat no, the tee command does something different. tee writes output to both the screen (stdout) and the file. Redirect does only the file.
–
David OneillJun 5 '14 at 9:16

If the meaning of foo > bar would depend on whether there is a command named bar that would make using redirection a lot harder and more error prone: Every time I want to redirect to a file I first had to check whether there's a command named like my destination file.

ls | grep file.txt --> this command sends the output of the ls to grep command through
the use of pipe(|), and the grep command searches for file.txt in the in the input provided to it by the previous command.

If you had to perform the same task using the first scenario, then it would be :-

ls > log.txt; grep 'file.txt' log.txt

So Pipe is used to send the output to other command whereas to redirect is used to redirect the output to some file.

You can think of redirects like this: cat [<infile] [>outfile]. This implies order doesn't matter: cat <infile >outfile is the same as cat >outfile <infile. You can even mix redirects up with other arguments: cat >outfile <infile -b and cat <infile -b >outfile are both perfectly fine. Also you can string together more than one input or output (inputs will be read sequentially and all output will be written to each output file): cat >outfile1 >outfile2 <infile1 <infile2. The target or source of a redirect can be either a filename or the name of a stream (like &1, at least in bash).

But pipes totally separate one command from another command, you can't mix them in with arguments:

[command1] | [command2]

The pipe takes everything written to standard output from command1 and sends it to the standard input of command2.

You can also combine piping and redirection. For example:

cat <infile >outfile | cat <infile2 >outfile2

The first cat will read lines from infile, then simultaneously write each line to outfile and send it to the second cat.

In the second cat, standard input first reads from the pipe (the contents of infile), then reads from infile2, writing each line to outfile2. After running this, outfile will be a copy of infile, and outfile2 will contain infile followed by infile2.

Finally, you actually do something really similar to your example using "here string" redirection (bash family only) and backticks:

grep blah <<<`ls`

will give the same result as

ls | grep blah

But I think the redirection version will first read all of the output of ls into a buffer (in memory), and then feed that buffer to grep one line at a time, whereas the piped version will take each line from ls as it emerges, and pass that line to grep.

Nitpick: order matters in redirection if you redirect one fd to another: echo yes 1>&2 2>/tmp/blah; wc -l /tmp/blah; echo yes 2>/tmp/blah 1>&2; wc -l /tmp/blah Further, redirection to a file will only use the last redirection. echo yes >/tmp/blah >/tmp/blah2 will only write to /tmp/blah2.
–
muruAug 23 '14 at 22:49

Redirect is not actually argument to the program. The program will not know or care where its output goes (or input comes from). It's just way of telling bash how to arrange things before running the program.
–
Alois MahdalApr 23 at 18:33