1

I have a dummy question for you, I am trying to extract some lines from a file beginning by a special string of characters and to copy them into a file. I tried :

cat /dev/ttyACM0 | grep "something" > essai

The file is created but it contains nothing!

Nicolas
  • 11

1 Answers1

3

For efficiency, grep and many other commands use buffered I/O, that is, they read large blocks of data at once (rather than, say, one character at a time), and do not output data until a certain amount has been amassed (rather than, say, writing a line at a time or a character at a time)

But, when a program's input is from a terminal (such as your serial port), the operating system does the program a favor and returns a line at a time (the program can change this by putting the terminal into raw or noncanonical mode; most don't).

And when a program uses the stdio library, standard output to a terminal (the documentation calls this an "interactive device") is, by default, line buffered, but output to a file or pipe is fully buffered.

A program using the stdio library can choose full buffering, line buffering, or no buffering by calling setvbuf. It can also call fflush to force a write whenever it wishes.

GNU grep takes a --line-buffered option, which will run the following code in the function that outputs a matching line:

if (line_buffered)
  fflush (stdout);

Putting all the pieces together:

With this command:

cat /dev/ttyACM0 | grep "something" > essai

cat will read a line at a time from /dev/ttyACM0. After it has amassed a few kilobytes of output, it will write to the pipe. It will repeat this until the read returns a count of zero or fails (which probably won't happen until the serial port goes offline).

grep will read a few kilobytes at a time from the pipe, and after it has amassed a few kilobytes of output, it will write to the essai fle. It will repeat this until the read returns a count of zero or fails, which will happen if and when the cat process exits.

So you won't see anything appear in the essai file until grep has found a few kilobytes' worth of matching lines.

To get output written to the file more promptly, you can give GNU grep that option:

grep --line-buffered < /dev/ttyACM0 > essai

Since it's reading from a serial port, it will be line buffered, and the --line-buffered option will make output line buffered as well.

Mark Plotnick
  • 25,413
  • 3
  • 64
  • 82