0

In the following Unix command (I’m in zsh), I’d like to have a blank line appear between the head and tail of a long text file for readability.

Here’s the command:

cat LongTextFile.txt | tee >(head) >(tail) >/dev/null

I’m already aware of

(head; echo; tail) < LongTextFile.txt

but I’m wondering if it’s possible to use the tee command.

Mark Cowan
  • 93
  • 7
  • 1
    If you are not going to output to a file? Why use tee? – Raman Sailopal Jan 02 '21 at 18:55
  • @Raman Sailopal I don’t know that I necessarily need to. I’m just learning UNIX and want to know if the pipe operator can be used to show the head and tail of a long file, with a blank line in between. This seems to be a simple thing, but I can’t get it to work. – Mark Cowan Jan 02 '21 at 19:36
  • 2
    Both `>(head)` and `>(tail)` are executed asynchronously. There's no guarantee (though it is exceedingly likely) that you will even get the output of `head` first. – chepner Jan 02 '21 at 23:04
  • 1
    Note that `(head; echo; tail)` is not strictly safe either, as `head` can consume more lines of input than it needs to output, possibly consuming input you intended `tail` to get. – chepner Jan 02 '21 at 23:05
  • 1
    @RamanSailopal Because `tee` doesn't just output to a file; it outputs to one **or more** files, and those files can usefully be Bash process substitutions. – Kaz Jan 05 '21 at 16:32
  • I understand that but since the poster had already found an alternate solution, I was interested in the reason for focusing on tee. – Raman Sailopal Jan 05 '21 at 17:45
  • I think @Kaz understands what I was trying to get at. But after reading this [thread](https://stackoverflow.com/questions/8624669/unix-head-and-tail-of-file), I’m not sure that there’s a simple solution. – Mark Cowan Jan 06 '21 at 21:02

3 Answers3

1

Here you go, this works in Zsh:

print -l "$(head LongTextFile.txt)" '' "$(tail LongTextFile.txt)"
Marlon Richert
  • 5,250
  • 1
  • 18
  • 27
  • @MarionRichert Thank you for answering, but I was looking for a command that uses piping. – Mark Cowan Jan 06 '21 at 21:07
  • I’m just learning UNIX and am testing the boundaries of what the pipe operator can do. I’ve made a note of your alternate solution for future reference. Thanks. – Mark Cowan Jan 17 '21 at 18:39
1

The process substitutions >(head) >(tail) are not sequenced; they run in parallel. head and tail are running concurrently. tee is reading its standard input and distributing it to those two processes. So there is no concept of "between them" where we could insert a newline.

You're just lucky that when the file is long enough, head has a chance to finish before tail starts outputting anything.

If the file is so small that head and tail overlap, you may get interleaved output, or reordered output, depending on the exact buffering going on.

Kaz
  • 55,781
  • 9
  • 100
  • 149
0

Try:

seq 100 | { s=$(cat); head <<<$s; echo; tail <<<$s; }
aggu
  • 93
  • 2
  • 7