1

In what ways are pipes different from variable assignments?

I know you can't use null bytes. What other examples are there?

What about for piping in something like the following yes | cat? I notice it outputs the y while assigning

test=`yes`

doesn't output anything. Is the entire command executed before it pipes the data while cat is being executed?

William
  • 1,061

3 Answers3

1

Piping

yes is a command that repeatedly outputs a string (defaults to "y") until killed. See man yes

cat is a command that outputs to STDOUT everything it receives on STDIN or the concatenation of all the files listed as parameters. See man cat

The pipe (|) redirects the STDOUT from the previous command to the STDIN of the next command.

Therefore, piping to cat is a waste of CPU cycles.

Variable assignment

Variable assignment allows you to temporarily store a string in memory.

Example:

$ test="this is a string!"
$ echo $test
this is a string!

If you want to store the result of a command in a variable, you would need to use a subshell.

Example:

$ echo "file contents :)" > test.file
$ test="$(cat test.file)"
$ echo $test
file contents :)

Reference

For detailed usage of bash, see https://www.gnu.org/software/bash/manual/bash.html

1

Pipelines are very much what their name suggests: they offer a way to stream data from one pipeline member to the next. Handling streams of unbounded size is possible. Cases where processing an endless stream make sense include those where progress or statistics about the contents seen so far are printed from time to time, and where the user can kill the pipeline whenever they want.

On the other hand, the shell substitution construct (backquotes or $()) will not complete until the enclosed statement terminates. Since the statement in your example, yes, does not terminate, neither does $(yes).

I would say that's one way in which assignment and piping differ tremendously; one can't really assign a value of infinite length to a variable, but piping one is fine and works.

dhag
  • 15,736
  • 4
  • 55
  • 65
  • So what if the command never completes will the data even be sent to the next command cat? Is that why yes | echo does nothing? – William Nov 18 '15 at 23:08
  • Piping data from a command that doesn't terminate is OK, whether it sends a finite or, as in the case of yes, infinite amount of data. In the case of yes | echo, the pipeline terminates because the command echo does not read its input: it simply exits after printing a single newline. The writing process, yes, will then receive a SIGPIPE signal as it tries to write, and will exit. – dhag Nov 19 '15 at 01:29
1
test=`yes` 

will attempt to read the complete output of yes and assign that to the variable test.

Since the output of yes is infinite, this assignment will invoke an infinite loop.

Under the hood, it uses the pipe operating system mechanism, just like the | operation does.

test=`yes`

is kind of like

yes | thisShell.slurpInputAndSaveToVariable test

cat doesn't try to slurp its whole input, which makes it possible for yes and cat to run concurrently as a streaming producer (and infinite one in this case) and consumer pair.

Petr Skocik
  • 28,816
  • What is an example where of a piping command that runs infinitely completes something? – William Nov 19 '15 at 03:11
  • yes |head -3 . head will only read 3 lines and then close. Upon closing its stdin (the output end of the pipe) the next write to the other end will cause the OS to kill the writing process with SIGPIPE, ending the infinite loop very quickly. – Petr Skocik Nov 19 '15 at 03:14