Cursor disappears when running `top -n1 | head`

Best way IMHO is to make top use "batch" mode (-b flag) which is intended to be used with non-interactive use cases such as piping to another program or to a file.

So, this

top -n1 -b | head

won't be leaving the shell without a cursor.

As for the why the cursor disappears...

Since top is an interactive program, it "messes" with the terminal in order to grab input, scroll content, etc, and it hides the cursor.

When terminating it has to restore the cursor and the display status it found before being called, and it does so by sending one or more control codes to the terminal itself.

By piping the command through head, this control code won't get through (head prints just the first 10 lines by default, and the output of both top and the control codes to restore the terminal state is always >10 lines).

In fact, if you give head enough lines to print, the cursor appears!

For example,

top -n1 | head -n 100

leaves a cursor on my system.


I wasn't able to recreate this behavior everywhere, but it does show up on Ubuntu 18.04


It is instructive to examine hex dumps of the top output:

$ top -n1 | head -n1 | xxd
00000000: 1b5b 3f31 681b 3d1b 5b3f 3235 6c1b 5b48  .[?1h.=.[?25l.[H
00000010: 1b5b 324a 1b28 421b 5b6d 746f 7020 2d20  .[2J.(B.[mtop - 
00000020: 3133 3a34 333a 3034 2075 7020 3120 6d69  13:43:04 up 1 mi
00000030: 6e2c 2020 3120 7573 6572 2c20 206c 6f61  n,  1 user,  loa
00000040: 6420 6176 6572 6167 653a 2030 2e38 312c  d average: 0.81,
00000050: 2030 2e35 342c 2030 2e32 321b 2842 1b5b   0.54, 0.22.(B.[
00000060: 6d1b 5b33 393b 3439 6d1b 2842 1b5b 6d1b  m.[39;49m.(B.[m.
00000070: 5b33 393b 3439 6d1b 5b4b 0a              [39;49m.[K.
$ top -n1 | tail -n1 | xxd
00000000: 1b5b 3f31 326c 1b5b 3f32 3568 1b5b 4b    .[?12l.[?25h.[K
$ 

In particular, the sequences starting 0x1b5b3f are ANSI escape sequences, which effectively are meta-data to control things like cursor position and text colour.

In particular, towards the start of the first line of top output, there is ESC [?25l, and towards the end of the last line is ESC [?25h. As per the wikipedia page, these are the respective codes to hide and show the cursor.

By piping the top -n1 output to head, the terminal will receive the hide-cursor command at the start, but not the show-cursor command at the end, and hence the cursor will remain invisible until some other action turns it on again.

@MrShunz suggestion to use the -b option to top is right on. This option disables all of the ANSI escape sequences in top's output, instead just outputting plain ASCII printable text. No cursors will be harmed during the execution of top with -b:

$ top -b -n1 | head -n1 | xxd
00000000: 746f 7020 2d20 3133 3a35 393a 3236 2075  top - 13:59:26 u
00000010: 7020 3138 206d 696e 2c20 2031 2075 7365  p 18 min,  1 use
00000020: 722c 2020 6c6f 6164 2061 7665 7261 6765  r,  load average
00000030: 3a20 302e 3134 2c20 302e 3036 2c20 302e  : 0.14, 0.06, 0.
00000040: 3037 0a                                  07.
$