0

Get all processes whose name contain firefox and exclude grep process,it is no use to show all processes here,omit many lines.

ps aux | grep  [f]irefox
debian      7069  1.0  4.4 3134148 359168 ?      Sl   11:58   0:12 /usr/lib/firefox-esr/firefox-esr
debian      7128  0.0  0.4 223884 36824 ?        Sl   11:58   0:00 /usr/lib/firefox-esr/firefox-esr -contentproc -parentBuildID 20241118130310 -prefsLen 28341 -prefMapSize 249085 -appDir /usr/lib/firefox-esr/browser {0c853969-95e1-4db0-9e95-eeaee3d4f814} 7069 true socket

The output does not contain header info in ps's command ,in order to get the header,add head -n1 after the pipe.

ps aux |(head -n 1 ;grep  [f]irefox)
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
debian      7069  0.9  4.4 3134148 361740 ?      Sl   11:58   0:13 /usr/lib/firefox-esr/firefox-esr
debian      7128  0.0  0.4 223884 36824 ?        Sl   11:58   0:00 /usr/lib/firefox-esr/firefox-esr -contentproc -parentBuildID 20241118130310 -prefsLen 28341 -prefMapSize 249085 -appDir /usr/lib/firefox-esr/browser {0c853969-95e1-4db0-9e95-eeaee3d4f814} 7069 true socket

Other bash command:

df
Filesystem     1K-blocks      Used Available Use% Mounted on
udev             3977796         0   3977796   0% /dev
tmpfs             804900      1356    803544   1% /run
/dev/sdb1      460349516 143209832 293681076  33% /
tmpfs            4024488    100444   3924044   3% /dev/shm
tmpfs               5120        16      5104   1% /run/lock

df | grep shm
tmpfs            4024488    101536   3922952   3% /dev/shm
df |(head -n1; grep shm)
Filesystem     1K-blocks      Used Available Use% Mounted on

Why can't get the below output when to execute df |(head -n1; grep shm)?

df |(head -n1; grep shm)
Filesystem     1K-blocks      Used Available Use% Mounted on
tmpfs            4024488    101536   3922952   3% /dev/shm

Why grep in "ps aux |(head -n 1 ;grep [f]irefox)" can get lines to match?
As expert user10489 point out:

The command df |(head -n1; grep shm) does this:

df generates some output
head takes all of the output, prints the first line, and then quits throwing away all the rest of what it read.
There is no output left for grep to take as input.

Another post can explore it in depth:

cat > raw.txt <<EOF
ID         DESCRIPTION
-----      --------------
2          item2
4          item4
1          item1
3          item3
EOF

I want to get the below sorted lines with header:

ID         DESCRIPTION
-----      --------------
1          item1
2          item2
3          item3
4          item4

Gilles Quénot get a simple solution--simple solution

{ head -2; sort -n; } <raw.txt

When command in {} get input redirect by <raw.txt,if head -2; run as user10489 say:head takes all of the output, prints the first line, and then quits throwing away all the rest of what it read.,why sort -n have lines to sort with?
The result would be

ID         DESCRIPTION
-----      --------------

No lines sorted!!!

3
  • You need to give up on this broken way of attempting this. It doesn't work. You've been told why. I just added a more detailed demonstration. I won't be updating this more. Commented Feb 15 at 6:11
  • This question has been asked before as well. I'd vote to close, but there's little chance I'd find the previous time it was asked without a few hours of looking for the previous duplicate. Commented Feb 15 at 6:18
  • 1
    @user10489 Reusing pipe data for different commands might fit the bill. Commented Feb 15 at 8:25

5 Answers 5

4

For the why part, @user10489 gave an answer.

Using awk:

 df | awk 'NR==1;/shm/'

NR==1 is like head -n1 and /shm/ is like grep shm

5
  • 1
    Simple and smart. Commented Feb 15 at 6:05
  • 1.Why for same code structure grep in "ps aux |(head -n 1 ;grep [f]irefox)" have lines to match? Commented Feb 15 at 6:06
  • 2.What happend in the buffer? Commented Feb 15 at 6:09
  • head takes all of the output, prints the first line, and then quits throwing away all the rest of what it read,There is no output left for grep to take as input. Commented Feb 15 at 6:09
  • 1
    This is a nice example. Basically you replace head with NR==1 and grep with the following pattern match. Since awk is the only program running, there is no conflict and awk splits the pieces nicely. Commented Feb 15 at 16:19
3

This doesn't work because pipes don't work that way.

The command df |(head -n1; grep shm) does this:

  • df generates some output
  • head takes all of the output, prints the first line, and then quits throwing away all the rest of what it read.
  • There is no output left for grep to take as input.

Even if head doesn't read all the data, it's going to read a buffer full, which will almost never be exactly one line, and it has no way to give leftover input back to feed it to the next command. That just isn't how pipes work, and it isn't how input buffering works. And implementing it differently would not be efficient. So there will always be some data missing that the second command doesn't see, potentially giving incomplete answers.

The alternative command in the other answer is the correct way to do this, rather than expecting data in a pipe to be magically and perfectly split between two commands.

Here's a more repeatable example:

$ yes this is some long text | head -2000 | (head -1 ; wc -l)
this is some long text
1644

This works as follows:

  • The yes command outputs the same line of text repeatedly
  • The first head command truncates the yes output to 2000 lines
  • The head in () reads a buffer full of text and prints the first line
  • The wc command counts the remaining lines As you may have noticed, wc got significantly fewer than 1999 lines.

Doing a little math, that's 355 lines missing, or (23 chars per line) at least 8165 characters.

Presuming a typical buffer size of 8192, 23 characters were printed for the first line, and another 4 characters were eaten at the beginning of the last (incomplete) line in that buffer, leaving 1644 lines for wc, with the first one short.

4
  • Why grep in "ps aux |(head -n 1 ;grep [f]irefox)" can get lines to match? Commented Feb 15 at 5:32
  • Either it doesn't work, or it works coincidentally. Or maybe you just think it works but actually a bunch of stuff is thrown away at the start that you didn't know about. Basically, output of ps aux is longer so it fills head's buffer, and the result of your suggested command is unreliable at best. Commented Feb 15 at 5:34
  • quits throwing away all the rest of what it read. ? NO,absolutely not ,please see my latest update. Commented Feb 15 at 5:42
  • @showkey you’re missing the most important part of all this — when pipes are used, the result isn’t seekable; your head + sort test reads from a file (raw.txt), which is seekable. Commented Feb 15 at 8:27
2

If awk reads all the input, it does not encounter the buffering issue. It can therefore selectively pipe everything after the header to sort via an awk pipe.

df | awk 'NR == 1 { print; next; } /^.dev/ { print | "sort"; }'

I don't have much shm, but I like to report my partitions in sequence, likewise ps output.

Wordy, but maybe worth declaring as a function in .bashrc.

In fact, bash reads lines without buffering, so something like this works too:

df | { read -r Hdr; printf '%s\n' "$Hdr"; grep '^.dev' | sort; }
1

By using grep's regular expressions, one could:

df | grep -E 'shm|1K-blocks`

which matches lines containing either 'shm' OR '1K-blocks'

3
  • 1
    Not relevant to the topic,why "df |(head -n1; grep shm)" can't work? Commented Feb 15 at 5:00
  • More short."df | grep 'shm\|1K-blocks'" Commented Feb 15 at 5:01
  • @showkey Because head -n1 outputs the first line of STDIN, and discards the rest, so grep has nothing to read. Read man head. U&L is a Q&A site, not a conversation site. If you have new information on your original question, edit the question and add it. If you have a new question, How to Ask it. Do not try to start conversations in a Comment. Commented Feb 15 at 17:44
-1

1.{ head -2; sort -n; } <raw.txt can work, here is the reason--redirection and pipe.

2.Why ps aux |(head -n 1 ;grep [f]irefox) can work?
Buffer matters.

yes this is some long text | head -355 | (head -1 ; wc -l)
this is some long text
0
yes this is some long text | head -356 | (head -1 ; wc -l)
this is some long text
0
yes this is some long text | head -357 | (head -1 ; wc -l)
this is some long text
1
yes this is some long text | head -358 | (head -1 ; wc -l)
this is some long text
2

user10489's opinion is right, "basically, output of ps aux is longer so it fills head's buffer".

For the command ps aux |(head -n 1 ;grep [f]irefox),it seems like that ps aux output many lines filling many pages ,head -n 1 read out only the first page in the buffer,content whose line number is larger than 1 in the first page would be read out;other info without in the first page passed to grep to match.
Count the size in one page:

yes this is some long text | head -357 | (head -1 ; wc -c)
this is some long text
19

One line here contains 23 characters:

yes this is some long text | head -1|wc -c
23

Then:

356*23+(23-19)=8192

3.Write the head then add matched line.

df | head -1 ;(df | grep shm)
Filesystem     1K-blocks      Used Available Use% Mounted on
tmpfs            4024488     99660   3924828   3% /dev/shm
3
  • Note that the output from yes is 23 bytes per line. 356 lines is 8188 bytes, and 357 lines is 8211 bytes. With a buffer of 8 KiB, i.e. 8192 bytes, the first head would read a bit more than 356 lines and pass the rest off to the next part of the pipeline. On your system, you can therefore assume that head reads its input in chunks of 8 KiB. Commented Feb 15 at 9:05
  • 356*23+(23-19)=8192 Commented Feb 15 at 9:19
  • @showkey yes, see head eats extra characters for details. Commented Feb 15 at 10:29

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.