Given the following 3 scripts:
printf 'a\nb\nc\n' > file && { head -n 1; cat; } < file
printf 'a\nb\nc\n' | { head -n 1; cat; }
{ head -n 1; cat; } < <(printf 'a\nb\nc\n')
I'd expect the output from each to be:
a
b
c
but for some of those, on some systems, that is not the case. For example, on cygwin:
$ printf 'a\nb\nc\n' > file && { head -n 1; cat; } < file
a
b
c
$ printf 'a\nb\nc\n' | { head -n 1; cat; }
a
$ { head -n 1; cat; } < <(printf 'a\nb\nc\n')
a
What is causing the different output from those scripts?
Additional info - this is apparently not just a head
problem:
$ printf 'a\nb\nc\n' | { sed '1q'; cat; }
a
$ printf 'a\nb\nc\n' | { awk '1;{exit}'; cat; }
a
$ { sed '1q'; cat; } < <(printf 'a\nb\nc\n')
a
$ { awk '1;{exit}'; cat; } < <(printf 'a\nb\nc\n')
a
What would be a robust, POSIX way in shell (i.e. without just invoking awk or similar once to do everything) to read some number of lines from input and leave the rest for a different command regardless of whether the input is coming from a pipe or a file?
This question was inspired by comments under an answer to sort the whole .csv based on the value in a certain column.
GNU sed
, you can use the-u
option to avoid the buffering issue. Wonder why similar option isn't available for other commands though. – Sundeep Jul 04 '23 at 07:41sh
usingtail
andperl
(see this Answer). So it seems that some tools which may not be "defined" by POSIX still honor/respect POSIX definitions? If so, wouldn't those answers be useful? – jubilatious1 Jul 04 '23 at 21:39(i=<LINES_TO_READ>; while [ $((i=i-1)) -ge 0 ]; do read; done; <command to read the rest>)
? – aviro Jul 05 '23 at 10:57