1

I am a relatively experienced user in Linux. I want to understand better when it makes sense to use the pipe in Unix/Linux.

According to all book references, pipe | is used to connect commands together from left to right. When used with common commands such as ls, ps, echo, it is simple to understand that the pipe works very well because the previous commands produce simply an output without opening things such as a buffer viewer (e.g. less).

So if I execute ls | tr -d 'a', we all know things work. But if I execute top -n 1 | grep 'average', things start to come a little strange. In fact, if we use a screen oriented command left to the pipe, the pipe operator itself tries to redirect the output from that command and sometimes it is not easy to understand which kind of output redirects. I think this is due to a wrong usage of the pipe operator in such cases.

The question is: "When we should use the pipe operator and what happens if I try to use the pipe right to some commands like top and other screen oriented commands?"

Thank you.

roaima
  • 107,089
  • 14
  • 139
  • 261
  • 1
    This might help: https://unix.stackexchange.com/questions/30759/whats-a-good-example-of-piping-commands-together – Andy Dalton Oct 24 '22 at 20:40

1 Answers1

1

The pipe operator (|) connects two commands (or command lists). The output (stdout) from the one on the left is attached to the input (stdin) of the one on the right. It is up to you to ensure that the output of the first is suitable for input to the second. Note that usually the error channel (stderr) is not redirected through the pipe and is written directly to the terminal from any process in the pipeline.

In the case of top, it assumes it's writing to a terminal in an interactive session. You can use the -b flag to tell it that it should assume a batch environment; this switches off the terminal positioning sequences, colour, and keyboard input.

top -b -n1 | grep average
top - 21:43:52 up 4 days,  9:49,  0 user,  load average: 0.00, 0.00, 0.00

Some commands, such as ls detect when they are writing directly to a terminal or some other output stream and modify their output appropriately. For example, in a directory with several files, compare ls and ls | cat.

roaima
  • 107,089
  • 14
  • 139
  • 261
  • "It is up to you to ensure that the output of the first is suitable for input to the second" – Removing this requirement is, in fact, one of the biggest improvements of more modern approaches to piping (such as e.g. PowerShell's Strongly-Typed-but-automatically-adapted pipes) compared to the POSIX sh approach. – Jörg W Mittag Oct 25 '22 at 11:01
  • I tried to execute the ls command in both ways but I cannot notice a difference. Can you help me to understand? Thank you. – Angelo Giannuzzi Oct 25 '22 at 11:04
  • @JörgWMittag indeed. When I was learning PowerShell it took me a while to realise that the pipe operator is _effectively_ (if not actually) passing objects around. This is such a significant difference I felt it was important to identify it here. – roaima Oct 25 '22 at 11:11
  • Please can you answer me? @roaima – Angelo Giannuzzi Oct 25 '22 at 20:45
  • @AngeloGiannuzzi if you can't see a difference then I would guess you've got `ls` defined as an alias that breaks its normal behaviour. You could try with either `\ls` or `command ls`, either of which should bypass any alias setting – roaima Oct 25 '22 at 21:12
  • 1
    I noticed that when using ls without '| cat', the output is splitted among several columns. Is It right? – Angelo Giannuzzi Oct 27 '22 at 10:39
  • @AngeloGiannuzzi exactly. If `ls` is run in a terminal it will list the files in multiple columns across the screen. But if it's run in a pipeline it will list one file per line – roaima Oct 27 '22 at 10:41
  • @roaima let us suppose i type "sudo -i > file". I would expect that " [sudo] password for user:" is redirected to "file" but this does not happen. Why not? – Angelo Giannuzzi Nov 10 '22 at 11:26
  • @AngeloGiannuzzi what use would that be if it was? The prompt is directed to the user (probably using _stderr_, which isn't redirected in your example of `sudo -i >file`). See an answer to [What is regarded as "ideal" in relation to using stdout/stderr for output in different situations?](https://unix.stackexchange.com/a/247166/100397) for a better explanation, and [How to tell if output of a command or shell script is stdout or stderr](https://unix.stackexchange.com/q/186449/100397) for the question I think you're nearly asking – roaima Nov 10 '22 at 13:22