Difference in pipe and file redirection - BASH

独自空忆成欢 提交于 2021-02-18 08:10:29

问题


Redirection is used to redirect stdout/stdin/stderr! Ex: ls > log.txt.

Pipes are used to give the output of a command as input to another command. Ex: ls | grep file.txt

Why exactly are these two operators doing the same thing?

Why not just write ls > grep to pass the output through, isn't this just a kind of redirection also?

I realize Linux is "Do one thing and do it well", so there has to be more of a logical reason that I'm missing.


回答1:


You do need a differentiating syntax feature - and using > vs. | will do just fine.

If you used > in both scenarios, how would you know whether

ls > grep

is trying to write to a file named grep or send input to the grep command?

grep is perhaps not the best example, as you may then be tempted to disambiguate by the presence of grep's mandatory arguments; however, (optionally) argument-less commands do exist, such as column.
that other guy offers another example in the comments: test may refer to a test output file or to the argument-less invocation of the standard test command.


Another way of looking at it:

Your suggestion is essentially to use > as a generic send-output-somewhere operator, irrespective of the type of target (file vs. command).

However, that only shifts the need for disambiguation, and then you have to disambiguate when specifying the target - is it a file to output to or a command to run?

Given that the shell also has an implicit disambiguation feature when it comes to the first token of a simple command - foo [...] only ever invokes a command - differentiating at the level of the operator - > for outputting to files, | for sending to commands - is the sensible choice.




回答2:


This would actually make > do two things, open a file or run a new program, depending on what the operand is. (Ignoring the ambiguity when the argument is the name of an executable file: do we overwrite it or run it?)


bash and some other shells provide additional syntax (process substitution) that does technically replace the need for |, although not in a way that you would choose to use it over a pipe. For instance, you can write

ls > >(grep regex)

>(...) is treated as the "name" of a file (in fact, you can run echo >(true) to see what that file name is), whose contents are provided to the enclosed command as input. So now, instead of a single operator | that handles connecting output from A to the input of B, you have one operator > to redirect output, and another operator to redirect input.

It's also symmetrical:

grep regex < <(ls)
# or grep regex <(ls), since grep can read from standard input or a named file

<(...) is the "name" of an input file whose contents come from the output of the enclosed command.

The benefit of process substitution (and their underlying basis, named pipes) is when you want one process to write to many processes:

command1 | tee >(command2) >(command3) >(command4)

or for one process to read from many processes:

diff <(command1) <(command2)



回答3:


They are not doing the same job. If you were to take that example:

ls > grep

This is taking the output of ls and writing it to a file called grep.

Now if you were to do something like:

ls | grep '.*.txt'

This will take the output of ls and grep for any txt files. They in no way provide the same outcome.



来源:https://stackoverflow.com/questions/33531747/difference-in-pipe-and-file-redirection-bash

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!