Reputation: 1295
how can one have multiple commands (collected together) at the same position in a pipe? i.e. what comes before in the pipe gets fed into each of those commands separately and sequentially, and their combined output gets fed into the next step of the pipe. For example, how could I make some variation of this pipe
echo -e "1\n2\n3" | { head -1; tail -1; } | xargs echo
print 1 3
, instead of just 1
?
Thanks
Upvotes: 1
Views: 55
Reputation: 158050
what comes before in the pipe gets fed into each of those commands separately and sequentially, and their combined output gets fed into the next step of the pipe
This is not possible since of the nature of a pipe. Once data is read from a pipe it gets removed from the pipe. That's why there can be only one reader.
I would copy the output of the first command into a temporary file and than feed it to both commands head
and tail
. If you launch head
and tail
in a subshell you can feed their combined output to another command:
Btw, a code block between curly brackets does not launch a subshell. You need to use parentheses. The following command seems the closest to what you want:
echo -e "1\n2\n3" > file.tmp ; ( head -1 file.tmp ; tail -qn1 file.tmp; rm file.tmp ) | next_command
About the special use case: Printing the first and the last line from a file
I would use sed
for that purpose:
sed -n '1p;$p'
This will print the first and the last line of a file. However it works only for files which contain at least two lines. If the file contains a single line it would get printed twice. You can get around this restriction using the following command:
sed -n 'x;s/^/1/;x;1p;${x;/11/{x;p}}'
The command above adds a 1
to the hold buffer on every line. At the end of the script (which could be after the first line) it checks if there are at least two 1
in the hold buffer and prints the last line if this is true.
Upvotes: 3