grep doesn't output until EOF if piped through cat
Clash Royale CLAN TAG#URR8PPP
up vote
20
down vote
favorite
Given this minimal example
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; )
it outputs LINE 1
and then, after one second, outputs LINE 2
, as expected.
If we pipe this to grep LINE
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | grep LINE
the behavior is the same as in the previous case, as expected.
If, alternatively, we pipe this to cat
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | cat
the behavior is again the same, as expected.
However, if we pipe to grep LINE
, and then to cat
,
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | grep LINE | cat
there is no output until one second passes, and both lines appear on the output immediately, which I did not expect.
Why is this happening and how can I make the last version to behave in the same way as the first three commands?
bash grep pipe
add a comment |Â
up vote
20
down vote
favorite
Given this minimal example
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; )
it outputs LINE 1
and then, after one second, outputs LINE 2
, as expected.
If we pipe this to grep LINE
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | grep LINE
the behavior is the same as in the previous case, as expected.
If, alternatively, we pipe this to cat
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | cat
the behavior is again the same, as expected.
However, if we pipe to grep LINE
, and then to cat
,
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | grep LINE | cat
there is no output until one second passes, and both lines appear on the output immediately, which I did not expect.
Why is this happening and how can I make the last version to behave in the same way as the first three commands?
bash grep pipe
cat
concatenates files. What are you trying to do by piping intocat
?
â Douglas Held
Sep 5 at 20:09
15
@DouglasHeld When called without arguments,cat
simply readsstdin
and outputs intostdout
. Of course, I came up with this question with a lot of complex stuff in place ofecho
andcat
, but these turned out to be irrelevant, since the problem shows up with much simpler examples.
â lisyarus
Sep 5 at 21:11
3
@DouglasHeld: Piping to cat is often useful to force stdout to not be a terminal. For instance, this is an easy way to get many commands to not use colorized output.
â wchargin
Sep 7 at 5:01
I swear this is a dupliciate of another question on Stack Overflow!
â iBug
Sep 7 at 6:46
add a comment |Â
up vote
20
down vote
favorite
up vote
20
down vote
favorite
Given this minimal example
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; )
it outputs LINE 1
and then, after one second, outputs LINE 2
, as expected.
If we pipe this to grep LINE
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | grep LINE
the behavior is the same as in the previous case, as expected.
If, alternatively, we pipe this to cat
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | cat
the behavior is again the same, as expected.
However, if we pipe to grep LINE
, and then to cat
,
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | grep LINE | cat
there is no output until one second passes, and both lines appear on the output immediately, which I did not expect.
Why is this happening and how can I make the last version to behave in the same way as the first three commands?
bash grep pipe
Given this minimal example
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; )
it outputs LINE 1
and then, after one second, outputs LINE 2
, as expected.
If we pipe this to grep LINE
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | grep LINE
the behavior is the same as in the previous case, as expected.
If, alternatively, we pipe this to cat
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | cat
the behavior is again the same, as expected.
However, if we pipe to grep LINE
, and then to cat
,
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | grep LINE | cat
there is no output until one second passes, and both lines appear on the output immediately, which I did not expect.
Why is this happening and how can I make the last version to behave in the same way as the first three commands?
bash grep pipe
bash grep pipe
asked Sep 5 at 15:08
lisyarus
20316
20316
cat
concatenates files. What are you trying to do by piping intocat
?
â Douglas Held
Sep 5 at 20:09
15
@DouglasHeld When called without arguments,cat
simply readsstdin
and outputs intostdout
. Of course, I came up with this question with a lot of complex stuff in place ofecho
andcat
, but these turned out to be irrelevant, since the problem shows up with much simpler examples.
â lisyarus
Sep 5 at 21:11
3
@DouglasHeld: Piping to cat is often useful to force stdout to not be a terminal. For instance, this is an easy way to get many commands to not use colorized output.
â wchargin
Sep 7 at 5:01
I swear this is a dupliciate of another question on Stack Overflow!
â iBug
Sep 7 at 6:46
add a comment |Â
cat
concatenates files. What are you trying to do by piping intocat
?
â Douglas Held
Sep 5 at 20:09
15
@DouglasHeld When called without arguments,cat
simply readsstdin
and outputs intostdout
. Of course, I came up with this question with a lot of complex stuff in place ofecho
andcat
, but these turned out to be irrelevant, since the problem shows up with much simpler examples.
â lisyarus
Sep 5 at 21:11
3
@DouglasHeld: Piping to cat is often useful to force stdout to not be a terminal. For instance, this is an easy way to get many commands to not use colorized output.
â wchargin
Sep 7 at 5:01
I swear this is a dupliciate of another question on Stack Overflow!
â iBug
Sep 7 at 6:46
cat
concatenates files. What are you trying to do by piping into cat
?â Douglas Held
Sep 5 at 20:09
cat
concatenates files. What are you trying to do by piping into cat
?â Douglas Held
Sep 5 at 20:09
15
15
@DouglasHeld When called without arguments,
cat
simply reads stdin
and outputs into stdout
. Of course, I came up with this question with a lot of complex stuff in place of echo
and cat
, but these turned out to be irrelevant, since the problem shows up with much simpler examples.â lisyarus
Sep 5 at 21:11
@DouglasHeld When called without arguments,
cat
simply reads stdin
and outputs into stdout
. Of course, I came up with this question with a lot of complex stuff in place of echo
and cat
, but these turned out to be irrelevant, since the problem shows up with much simpler examples.â lisyarus
Sep 5 at 21:11
3
3
@DouglasHeld: Piping to cat is often useful to force stdout to not be a terminal. For instance, this is an easy way to get many commands to not use colorized output.
â wchargin
Sep 7 at 5:01
@DouglasHeld: Piping to cat is often useful to force stdout to not be a terminal. For instance, this is an easy way to get many commands to not use colorized output.
â wchargin
Sep 7 at 5:01
I swear this is a dupliciate of another question on Stack Overflow!
â iBug
Sep 7 at 6:46
I swear this is a dupliciate of another question on Stack Overflow!
â iBug
Sep 7 at 6:46
add a comment |Â
3 Answers
3
active
oldest
votes
up vote
39
down vote
accepted
When (at least GNU) grep
âÂÂs output is not a terminal, it buffers its output, which is what causes the behaviour youâÂÂre seeing. You can disable this either using GNU grep
âÂÂs --line-buffered
option:
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | grep --line-buffered LINE | cat
or the stdbuf
utility:
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | stdbuf -oL grep LINE | cat
Turn off buffering in pipe has more on this topic.
add a comment |Â
up vote
26
down vote
Simplified explanation
Like many utilities, this not being something peculiar to one program, grep
varies its standard output between being line buffered and fully buffered. In the former case, the C library buffers output data in memory until either the buffer holding those data is filled or a linefeed character is added to it (or the program ends cleanly), whereupon it calls write()
to actually write the buffer contents. In the latter case, only the in-memory buffer becoming full (or the program ending cleanly) triggers the write()
.
More detailed explanation
This is the well-known, but slightly wrong, explanation. In fact, standard output is not line buffered but smart buffered in the GNU C library and BSD C library. Standard output is also flushed when reading standard input exhausts its in-memory buffer (of pre-read input) and the C library has to call read()
to fetch some more input and it is reading the beginning of a new line. (One reason for this is to prevent deadlock when another program connects itself to both ends of a filter and expects to be able to operate line-by-line, alternating between writing to the filter and reading from it; like "coprocesses" in GNU awk
for example.)
C library influence
grep
and the other utilities do this â or, more strictly, the C libraries that they use do this, because this is a defined feature of programming in the C language â based upon what they detect their standard output to be. If (and only if) it is not an interactive device, they choose full buffering, otherwise they choose smart buffering. A pipe is considered to be not an interactive device, because the definition of being an interactive device, at least in the world of Unix and Linux, is essentially the isatty()
call returning true for the relevant file descriptor.
Workarounds to disable full buffering
Some utilities like grep
have idiosyncratic options such as --line-buffered
that change this decision, which as you can see is mis-named. But a vanishingly small fraction of the filter programs that one could use actually have such an option.
More generally, one can use tools that dig into the specific internals of the C library and change its decision making (which have security problems if the program to be altered is set-UID, and are also specific to particular C libraries, and indeed are specific to programs written in or layered on top of the C language), or tools such as ptybandage
that do not change the internals of the program but simply interpose a pseudo-terminal as standard output so that the decision comes out as "interactive", to affect this.
Further reading
- https://unix.stackexchange.com/a/407472/5132
- https://unix.stackexchange.com/a/249801/5132
Underrated answer. Thanks for the info!
â Délisson Junio
Sep 5 at 17:37
1
If the phrase "line buffered" is a misnomer, then it's not really the fault ofgrep
, but of the underlying library calls,setbuf
/setvbuf
. I don't know of a reliable online reference for the C standard, but e.g. the Linux and FreeBSD man pages along with the POSIX description ofsetvbuf
call it "line buffered". Even the symbolic constant for it is_IOLBF
.
â ilkkachu
Sep 5 at 21:19
Well now you've learned better. This buffering strategy is described in the GNU C library doco, albeit briefly. Laurent Bercot is more forthright on the matter. I have mentioned it too.
â JdeBP
Sep 6 at 0:35
2
@ilkkachu The C standard does indeed use "line buffered". Per 7.21.3 Files, paragraph 3: "When a stream is unbuffered, ... When a stream is fully buffered, ... When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when a new-line character is encountered. ..." In fact, the C Standard uses the exact phrase "line buffered" five times. So it's not a misnomer.
â Andrew Henle
Sep 6 at 14:41
1
Furthermore, the approach described here as "smart buffering", as I understand it, seems to be just what the C standard describes as "line buffering". Specifically, in addition to flushing the buffer at newlines, "When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when [...] input is requested on an unbuffered stream, or when input is requested on a line buffered stream that requires the transmission of characters from the host environment." So this is not a GNU or BSD quirk, but rather what the language calls for.
â John Bollinger
Sep 6 at 22:44
 |Â
show 1 more comment
up vote
7
down vote
Use
grep --line-buffered
to make grep not buffer more than one line at a time.
add a comment |Â
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
39
down vote
accepted
When (at least GNU) grep
âÂÂs output is not a terminal, it buffers its output, which is what causes the behaviour youâÂÂre seeing. You can disable this either using GNU grep
âÂÂs --line-buffered
option:
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | grep --line-buffered LINE | cat
or the stdbuf
utility:
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | stdbuf -oL grep LINE | cat
Turn off buffering in pipe has more on this topic.
add a comment |Â
up vote
39
down vote
accepted
When (at least GNU) grep
âÂÂs output is not a terminal, it buffers its output, which is what causes the behaviour youâÂÂre seeing. You can disable this either using GNU grep
âÂÂs --line-buffered
option:
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | grep --line-buffered LINE | cat
or the stdbuf
utility:
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | stdbuf -oL grep LINE | cat
Turn off buffering in pipe has more on this topic.
add a comment |Â
up vote
39
down vote
accepted
up vote
39
down vote
accepted
When (at least GNU) grep
âÂÂs output is not a terminal, it buffers its output, which is what causes the behaviour youâÂÂre seeing. You can disable this either using GNU grep
âÂÂs --line-buffered
option:
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | grep --line-buffered LINE | cat
or the stdbuf
utility:
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | stdbuf -oL grep LINE | cat
Turn off buffering in pipe has more on this topic.
When (at least GNU) grep
âÂÂs output is not a terminal, it buffers its output, which is what causes the behaviour youâÂÂre seeing. You can disable this either using GNU grep
âÂÂs --line-buffered
option:
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | grep --line-buffered LINE | cat
or the stdbuf
utility:
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | stdbuf -oL grep LINE | cat
Turn off buffering in pipe has more on this topic.
answered Sep 5 at 15:12
Stephen Kitt
147k22321389
147k22321389
add a comment |Â
add a comment |Â
up vote
26
down vote
Simplified explanation
Like many utilities, this not being something peculiar to one program, grep
varies its standard output between being line buffered and fully buffered. In the former case, the C library buffers output data in memory until either the buffer holding those data is filled or a linefeed character is added to it (or the program ends cleanly), whereupon it calls write()
to actually write the buffer contents. In the latter case, only the in-memory buffer becoming full (or the program ending cleanly) triggers the write()
.
More detailed explanation
This is the well-known, but slightly wrong, explanation. In fact, standard output is not line buffered but smart buffered in the GNU C library and BSD C library. Standard output is also flushed when reading standard input exhausts its in-memory buffer (of pre-read input) and the C library has to call read()
to fetch some more input and it is reading the beginning of a new line. (One reason for this is to prevent deadlock when another program connects itself to both ends of a filter and expects to be able to operate line-by-line, alternating between writing to the filter and reading from it; like "coprocesses" in GNU awk
for example.)
C library influence
grep
and the other utilities do this â or, more strictly, the C libraries that they use do this, because this is a defined feature of programming in the C language â based upon what they detect their standard output to be. If (and only if) it is not an interactive device, they choose full buffering, otherwise they choose smart buffering. A pipe is considered to be not an interactive device, because the definition of being an interactive device, at least in the world of Unix and Linux, is essentially the isatty()
call returning true for the relevant file descriptor.
Workarounds to disable full buffering
Some utilities like grep
have idiosyncratic options such as --line-buffered
that change this decision, which as you can see is mis-named. But a vanishingly small fraction of the filter programs that one could use actually have such an option.
More generally, one can use tools that dig into the specific internals of the C library and change its decision making (which have security problems if the program to be altered is set-UID, and are also specific to particular C libraries, and indeed are specific to programs written in or layered on top of the C language), or tools such as ptybandage
that do not change the internals of the program but simply interpose a pseudo-terminal as standard output so that the decision comes out as "interactive", to affect this.
Further reading
- https://unix.stackexchange.com/a/407472/5132
- https://unix.stackexchange.com/a/249801/5132
Underrated answer. Thanks for the info!
â Délisson Junio
Sep 5 at 17:37
1
If the phrase "line buffered" is a misnomer, then it's not really the fault ofgrep
, but of the underlying library calls,setbuf
/setvbuf
. I don't know of a reliable online reference for the C standard, but e.g. the Linux and FreeBSD man pages along with the POSIX description ofsetvbuf
call it "line buffered". Even the symbolic constant for it is_IOLBF
.
â ilkkachu
Sep 5 at 21:19
Well now you've learned better. This buffering strategy is described in the GNU C library doco, albeit briefly. Laurent Bercot is more forthright on the matter. I have mentioned it too.
â JdeBP
Sep 6 at 0:35
2
@ilkkachu The C standard does indeed use "line buffered". Per 7.21.3 Files, paragraph 3: "When a stream is unbuffered, ... When a stream is fully buffered, ... When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when a new-line character is encountered. ..." In fact, the C Standard uses the exact phrase "line buffered" five times. So it's not a misnomer.
â Andrew Henle
Sep 6 at 14:41
1
Furthermore, the approach described here as "smart buffering", as I understand it, seems to be just what the C standard describes as "line buffering". Specifically, in addition to flushing the buffer at newlines, "When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when [...] input is requested on an unbuffered stream, or when input is requested on a line buffered stream that requires the transmission of characters from the host environment." So this is not a GNU or BSD quirk, but rather what the language calls for.
â John Bollinger
Sep 6 at 22:44
 |Â
show 1 more comment
up vote
26
down vote
Simplified explanation
Like many utilities, this not being something peculiar to one program, grep
varies its standard output between being line buffered and fully buffered. In the former case, the C library buffers output data in memory until either the buffer holding those data is filled or a linefeed character is added to it (or the program ends cleanly), whereupon it calls write()
to actually write the buffer contents. In the latter case, only the in-memory buffer becoming full (or the program ending cleanly) triggers the write()
.
More detailed explanation
This is the well-known, but slightly wrong, explanation. In fact, standard output is not line buffered but smart buffered in the GNU C library and BSD C library. Standard output is also flushed when reading standard input exhausts its in-memory buffer (of pre-read input) and the C library has to call read()
to fetch some more input and it is reading the beginning of a new line. (One reason for this is to prevent deadlock when another program connects itself to both ends of a filter and expects to be able to operate line-by-line, alternating between writing to the filter and reading from it; like "coprocesses" in GNU awk
for example.)
C library influence
grep
and the other utilities do this â or, more strictly, the C libraries that they use do this, because this is a defined feature of programming in the C language â based upon what they detect their standard output to be. If (and only if) it is not an interactive device, they choose full buffering, otherwise they choose smart buffering. A pipe is considered to be not an interactive device, because the definition of being an interactive device, at least in the world of Unix and Linux, is essentially the isatty()
call returning true for the relevant file descriptor.
Workarounds to disable full buffering
Some utilities like grep
have idiosyncratic options such as --line-buffered
that change this decision, which as you can see is mis-named. But a vanishingly small fraction of the filter programs that one could use actually have such an option.
More generally, one can use tools that dig into the specific internals of the C library and change its decision making (which have security problems if the program to be altered is set-UID, and are also specific to particular C libraries, and indeed are specific to programs written in or layered on top of the C language), or tools such as ptybandage
that do not change the internals of the program but simply interpose a pseudo-terminal as standard output so that the decision comes out as "interactive", to affect this.
Further reading
- https://unix.stackexchange.com/a/407472/5132
- https://unix.stackexchange.com/a/249801/5132
Underrated answer. Thanks for the info!
â Délisson Junio
Sep 5 at 17:37
1
If the phrase "line buffered" is a misnomer, then it's not really the fault ofgrep
, but of the underlying library calls,setbuf
/setvbuf
. I don't know of a reliable online reference for the C standard, but e.g. the Linux and FreeBSD man pages along with the POSIX description ofsetvbuf
call it "line buffered". Even the symbolic constant for it is_IOLBF
.
â ilkkachu
Sep 5 at 21:19
Well now you've learned better. This buffering strategy is described in the GNU C library doco, albeit briefly. Laurent Bercot is more forthright on the matter. I have mentioned it too.
â JdeBP
Sep 6 at 0:35
2
@ilkkachu The C standard does indeed use "line buffered". Per 7.21.3 Files, paragraph 3: "When a stream is unbuffered, ... When a stream is fully buffered, ... When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when a new-line character is encountered. ..." In fact, the C Standard uses the exact phrase "line buffered" five times. So it's not a misnomer.
â Andrew Henle
Sep 6 at 14:41
1
Furthermore, the approach described here as "smart buffering", as I understand it, seems to be just what the C standard describes as "line buffering". Specifically, in addition to flushing the buffer at newlines, "When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when [...] input is requested on an unbuffered stream, or when input is requested on a line buffered stream that requires the transmission of characters from the host environment." So this is not a GNU or BSD quirk, but rather what the language calls for.
â John Bollinger
Sep 6 at 22:44
 |Â
show 1 more comment
up vote
26
down vote
up vote
26
down vote
Simplified explanation
Like many utilities, this not being something peculiar to one program, grep
varies its standard output between being line buffered and fully buffered. In the former case, the C library buffers output data in memory until either the buffer holding those data is filled or a linefeed character is added to it (or the program ends cleanly), whereupon it calls write()
to actually write the buffer contents. In the latter case, only the in-memory buffer becoming full (or the program ending cleanly) triggers the write()
.
More detailed explanation
This is the well-known, but slightly wrong, explanation. In fact, standard output is not line buffered but smart buffered in the GNU C library and BSD C library. Standard output is also flushed when reading standard input exhausts its in-memory buffer (of pre-read input) and the C library has to call read()
to fetch some more input and it is reading the beginning of a new line. (One reason for this is to prevent deadlock when another program connects itself to both ends of a filter and expects to be able to operate line-by-line, alternating between writing to the filter and reading from it; like "coprocesses" in GNU awk
for example.)
C library influence
grep
and the other utilities do this â or, more strictly, the C libraries that they use do this, because this is a defined feature of programming in the C language â based upon what they detect their standard output to be. If (and only if) it is not an interactive device, they choose full buffering, otherwise they choose smart buffering. A pipe is considered to be not an interactive device, because the definition of being an interactive device, at least in the world of Unix and Linux, is essentially the isatty()
call returning true for the relevant file descriptor.
Workarounds to disable full buffering
Some utilities like grep
have idiosyncratic options such as --line-buffered
that change this decision, which as you can see is mis-named. But a vanishingly small fraction of the filter programs that one could use actually have such an option.
More generally, one can use tools that dig into the specific internals of the C library and change its decision making (which have security problems if the program to be altered is set-UID, and are also specific to particular C libraries, and indeed are specific to programs written in or layered on top of the C language), or tools such as ptybandage
that do not change the internals of the program but simply interpose a pseudo-terminal as standard output so that the decision comes out as "interactive", to affect this.
Further reading
- https://unix.stackexchange.com/a/407472/5132
- https://unix.stackexchange.com/a/249801/5132
Simplified explanation
Like many utilities, this not being something peculiar to one program, grep
varies its standard output between being line buffered and fully buffered. In the former case, the C library buffers output data in memory until either the buffer holding those data is filled or a linefeed character is added to it (or the program ends cleanly), whereupon it calls write()
to actually write the buffer contents. In the latter case, only the in-memory buffer becoming full (or the program ending cleanly) triggers the write()
.
More detailed explanation
This is the well-known, but slightly wrong, explanation. In fact, standard output is not line buffered but smart buffered in the GNU C library and BSD C library. Standard output is also flushed when reading standard input exhausts its in-memory buffer (of pre-read input) and the C library has to call read()
to fetch some more input and it is reading the beginning of a new line. (One reason for this is to prevent deadlock when another program connects itself to both ends of a filter and expects to be able to operate line-by-line, alternating between writing to the filter and reading from it; like "coprocesses" in GNU awk
for example.)
C library influence
grep
and the other utilities do this â or, more strictly, the C libraries that they use do this, because this is a defined feature of programming in the C language â based upon what they detect their standard output to be. If (and only if) it is not an interactive device, they choose full buffering, otherwise they choose smart buffering. A pipe is considered to be not an interactive device, because the definition of being an interactive device, at least in the world of Unix and Linux, is essentially the isatty()
call returning true for the relevant file descriptor.
Workarounds to disable full buffering
Some utilities like grep
have idiosyncratic options such as --line-buffered
that change this decision, which as you can see is mis-named. But a vanishingly small fraction of the filter programs that one could use actually have such an option.
More generally, one can use tools that dig into the specific internals of the C library and change its decision making (which have security problems if the program to be altered is set-UID, and are also specific to particular C libraries, and indeed are specific to programs written in or layered on top of the C language), or tools such as ptybandage
that do not change the internals of the program but simply interpose a pseudo-terminal as standard output so that the decision comes out as "interactive", to affect this.
Further reading
- https://unix.stackexchange.com/a/407472/5132
- https://unix.stackexchange.com/a/249801/5132
edited Sep 6 at 14:25
Anthony Geoghegan
7,30733852
7,30733852
answered Sep 5 at 15:51
JdeBP
29.6k460136
29.6k460136
Underrated answer. Thanks for the info!
â Délisson Junio
Sep 5 at 17:37
1
If the phrase "line buffered" is a misnomer, then it's not really the fault ofgrep
, but of the underlying library calls,setbuf
/setvbuf
. I don't know of a reliable online reference for the C standard, but e.g. the Linux and FreeBSD man pages along with the POSIX description ofsetvbuf
call it "line buffered". Even the symbolic constant for it is_IOLBF
.
â ilkkachu
Sep 5 at 21:19
Well now you've learned better. This buffering strategy is described in the GNU C library doco, albeit briefly. Laurent Bercot is more forthright on the matter. I have mentioned it too.
â JdeBP
Sep 6 at 0:35
2
@ilkkachu The C standard does indeed use "line buffered". Per 7.21.3 Files, paragraph 3: "When a stream is unbuffered, ... When a stream is fully buffered, ... When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when a new-line character is encountered. ..." In fact, the C Standard uses the exact phrase "line buffered" five times. So it's not a misnomer.
â Andrew Henle
Sep 6 at 14:41
1
Furthermore, the approach described here as "smart buffering", as I understand it, seems to be just what the C standard describes as "line buffering". Specifically, in addition to flushing the buffer at newlines, "When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when [...] input is requested on an unbuffered stream, or when input is requested on a line buffered stream that requires the transmission of characters from the host environment." So this is not a GNU or BSD quirk, but rather what the language calls for.
â John Bollinger
Sep 6 at 22:44
 |Â
show 1 more comment
Underrated answer. Thanks for the info!
â Délisson Junio
Sep 5 at 17:37
1
If the phrase "line buffered" is a misnomer, then it's not really the fault ofgrep
, but of the underlying library calls,setbuf
/setvbuf
. I don't know of a reliable online reference for the C standard, but e.g. the Linux and FreeBSD man pages along with the POSIX description ofsetvbuf
call it "line buffered". Even the symbolic constant for it is_IOLBF
.
â ilkkachu
Sep 5 at 21:19
Well now you've learned better. This buffering strategy is described in the GNU C library doco, albeit briefly. Laurent Bercot is more forthright on the matter. I have mentioned it too.
â JdeBP
Sep 6 at 0:35
2
@ilkkachu The C standard does indeed use "line buffered". Per 7.21.3 Files, paragraph 3: "When a stream is unbuffered, ... When a stream is fully buffered, ... When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when a new-line character is encountered. ..." In fact, the C Standard uses the exact phrase "line buffered" five times. So it's not a misnomer.
â Andrew Henle
Sep 6 at 14:41
1
Furthermore, the approach described here as "smart buffering", as I understand it, seems to be just what the C standard describes as "line buffering". Specifically, in addition to flushing the buffer at newlines, "When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when [...] input is requested on an unbuffered stream, or when input is requested on a line buffered stream that requires the transmission of characters from the host environment." So this is not a GNU or BSD quirk, but rather what the language calls for.
â John Bollinger
Sep 6 at 22:44
Underrated answer. Thanks for the info!
â Délisson Junio
Sep 5 at 17:37
Underrated answer. Thanks for the info!
â Délisson Junio
Sep 5 at 17:37
1
1
If the phrase "line buffered" is a misnomer, then it's not really the fault of
grep
, but of the underlying library calls, setbuf
/setvbuf
. I don't know of a reliable online reference for the C standard, but e.g. the Linux and FreeBSD man pages along with the POSIX description of setvbuf
call it "line buffered". Even the symbolic constant for it is _IOLBF
.â ilkkachu
Sep 5 at 21:19
If the phrase "line buffered" is a misnomer, then it's not really the fault of
grep
, but of the underlying library calls, setbuf
/setvbuf
. I don't know of a reliable online reference for the C standard, but e.g. the Linux and FreeBSD man pages along with the POSIX description of setvbuf
call it "line buffered". Even the symbolic constant for it is _IOLBF
.â ilkkachu
Sep 5 at 21:19
Well now you've learned better. This buffering strategy is described in the GNU C library doco, albeit briefly. Laurent Bercot is more forthright on the matter. I have mentioned it too.
â JdeBP
Sep 6 at 0:35
Well now you've learned better. This buffering strategy is described in the GNU C library doco, albeit briefly. Laurent Bercot is more forthright on the matter. I have mentioned it too.
â JdeBP
Sep 6 at 0:35
2
2
@ilkkachu The C standard does indeed use "line buffered". Per 7.21.3 Files, paragraph 3: "When a stream is unbuffered, ... When a stream is fully buffered, ... When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when a new-line character is encountered. ..." In fact, the C Standard uses the exact phrase "line buffered" five times. So it's not a misnomer.
â Andrew Henle
Sep 6 at 14:41
@ilkkachu The C standard does indeed use "line buffered". Per 7.21.3 Files, paragraph 3: "When a stream is unbuffered, ... When a stream is fully buffered, ... When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when a new-line character is encountered. ..." In fact, the C Standard uses the exact phrase "line buffered" five times. So it's not a misnomer.
â Andrew Henle
Sep 6 at 14:41
1
1
Furthermore, the approach described here as "smart buffering", as I understand it, seems to be just what the C standard describes as "line buffering". Specifically, in addition to flushing the buffer at newlines, "When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when [...] input is requested on an unbuffered stream, or when input is requested on a line buffered stream that requires the transmission of characters from the host environment." So this is not a GNU or BSD quirk, but rather what the language calls for.
â John Bollinger
Sep 6 at 22:44
Furthermore, the approach described here as "smart buffering", as I understand it, seems to be just what the C standard describes as "line buffering". Specifically, in addition to flushing the buffer at newlines, "When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when [...] input is requested on an unbuffered stream, or when input is requested on a line buffered stream that requires the transmission of characters from the host environment." So this is not a GNU or BSD quirk, but rather what the language calls for.
â John Bollinger
Sep 6 at 22:44
 |Â
show 1 more comment
up vote
7
down vote
Use
grep --line-buffered
to make grep not buffer more than one line at a time.
add a comment |Â
up vote
7
down vote
Use
grep --line-buffered
to make grep not buffer more than one line at a time.
add a comment |Â
up vote
7
down vote
up vote
7
down vote
Use
grep --line-buffered
to make grep not buffer more than one line at a time.
Use
grep --line-buffered
to make grep not buffer more than one line at a time.
answered Sep 5 at 15:10
choroba
24.8k34168
24.8k34168
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f467039%2fgrep-doesnt-output-until-eof-if-piped-through-cat%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
cat
concatenates files. What are you trying to do by piping intocat
?â Douglas Held
Sep 5 at 20:09
15
@DouglasHeld When called without arguments,
cat
simply readsstdin
and outputs intostdout
. Of course, I came up with this question with a lot of complex stuff in place ofecho
andcat
, but these turned out to be irrelevant, since the problem shows up with much simpler examples.â lisyarus
Sep 5 at 21:11
3
@DouglasHeld: Piping to cat is often useful to force stdout to not be a terminal. For instance, this is an easy way to get many commands to not use colorized output.
â wchargin
Sep 7 at 5:01
I swear this is a dupliciate of another question on Stack Overflow!
â iBug
Sep 7 at 6:46