Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does taking stdin from a file differ from receiving it over a pipe?

Tags:

bash

unix

pipe

Using bash I often want to get the headings of a large csv file and search the rest for a particular entry. I do this as follows.

$ (head -1; grep mike) < tmp.csv
name,age,favourite colour
mike,38,blue

But taking the input from cat, or any other command doesn't work - it seems grep never gets passed the remainder of the file.

$ cat tmp.csv | (head -1; grep mike)
name,age,favourite colour

Why is there different behaviour in these two cases?

like image 930
tlrrd Avatar asked Jan 27 '12 12:01

tlrrd


People also ask

Does pipe use STDIN?

Simple piping uses | character to send the STDOUT from one application to the STDIN of the next application. One nice thing about piping in Linux is that each application that is executed is run in parallel, so each application is processing its STDIN and sending its STDOUT as soon as it is received.

What is the difference between command line arguments and STDIN?

Any program cannot directly interact with Keyboard instead they interact with stdin . So if a program needs to take an input from user it will access stdin . Command line arguments are basically a method to take input from used along with the invocation of command to make the command do some specific task.

What is a STDIN file?

Short for standard input, stdin is an input stream where data is sent to and read by a program. It is a file descriptor in Unix-like operating systems, and programming languages, such as C, Perl, and Java.

Which command is used within a pipe to send output to a file and across a pipe?

Pipe shell command It is used to pipe, or transfer, the standard output from the command on its left into the standard input of the command on its right. # First, echo "Hello World" will send Hello World to the standard output.


1 Answers

The difference between reading from a pipe and reading from a file is that you can lseek on a file, but not on a pipe.

The behavior here looks (as seen through strace) like it's coming from head, not bash. head will read a buffer and find the appropriate number of lines, then lseek backwards to the point where the last-output line ended, leaving the file handle open at that place. As above, this works if it's reading a file, but not if it's reading from a pipe.

I can't think of any case other than what you're doing where this behavior in head makes sense, but there it is. Learn something new every day, I tell ya ...

like image 148
evil otto Avatar answered Sep 28 '22 03:09

evil otto