If I use:

strace echo 'a
c' > file

The bottom lines are:

write(1, "a\nb\nc\nd\n", 8)             = 8

but in

strace echo 'a
d' > /dev/pts/0

These lines are:

write(1, "a\n", 2)                      = 2
write(1, "b\n", 2)                      = 2
write(1, "c\n", 2)                      = 2
write(1, "d\n", 2)                      = 2

In second case, why does it is writing line by line, whereas in first case it is writing together. May be because terminal is character device, but I got definition of character device as:

A character (char) device is one that can be accessed as a stream of bytes (like a file).The only relevant difference between a char device and a regular file is that you can always move back and forth in the regular file, whereas most char devices are just data channels, which you can only access sequentially.

Edit: Shell is bash.

  • I'm mostly guessing here, but it might have to do with files being more likely to be cached or buffered?
    – DopeGhoti
    Commented Feb 20, 2019 at 18:44
  • This is not terminal input at all.
    – JdeBP
    Commented Feb 20, 2019 at 18:47
  • 3
    perhaps stdout's set for line-buffering. Without knowing which shell, there's no source-code to confirm that. Commented Feb 20, 2019 at 18:47
  • 2
    It's not a shell built-in. The questioner is running it under strace, notice.
    – JdeBP
    Commented Feb 20, 2019 at 18:48
  • sure: but strace won't change the behavior of /bin/echo. And the shell does the redirection anyway. It's probably a duplicate. :-) Commented Feb 20, 2019 at 18:49

1 Answer 1


This is very simple.

The external echo command that you are running from strace is very probably the one from GNU coreutils. This is written in the C programming language, and uses the C runtime library functions such as putchar() and fputs() to write what it needs to write to the program's standard output.

In the C language, output to standard output can be fully buffered, line buffered, or unbuffered. The rules for what happens are actually part of the C language specification, apply across operating systems, and are written in abstract terms of whether standard output "can be determined not to refer to an interactive device".

On Unix and Linux operating systems, the concrete way that they apply is that standard output is fully buffered if the isatty() function says that the file descriptor is not a terminal. That's what "an interactive device" is in this case. Standard output is otherwise line buffered, on your operating system. The C language standard does not mandate that latter. It is what the GNU C library additionally documents that it does, on top of what the C language standard says.

So when your echo command's standard output is not a terminal but a file, the C library in the program buffers up all of the individual writes to standard output and makes one big write() call, when the buffer is full or when the program finishes. Whereas when standard output is a terminal, the C library only buffers things until a linefeed character is output, at which point it write()s the contents of the buffer.

Hence the observed system calls.

Further reading


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .