12

Let's run cat and then type a then ^D - you will see that cat did not exit.

Compare it with cat + a + Enter + ^D - now cat did exit.

So, why two ^D presses are necessary to exit cat in the first case and only one ^D in second case?

thiagowfx
  • 1,249

1 Answers1

24

The answer can be found in the termios(3) man page:

   VEOF   (004, EOT, Ctrl-D) End-of-file character (EOF).  More precisely:
          this character causes the pending tty buffer to be sent  to  the
          waiting  user program without waiting for end-of-line.  If it is
          the first character of the line, the read(2) in the user program
          returns  0, which signifies end-of-file.  Recognized when ICANON
          is set, and then not passed as input.

The first ^D you press causes the line you have typed to be delivered to the cat, so it gets a read(2) result of a (one character, no EOL char). The second ^D causes read(2) to return 0, which signifies EOF to cat.

camh
  • 39,069
  • Occasionally, is the function of ^D in bash connected with this description? In other words, how it came to be that in some circumstances ^D means "delete character under cursor" and in other circumstances this same keycode means "exit bash"? – Igor Liferenko Jul 09 '17 at 01:40
  • 1
    In the first case, some program has changed the tty settings so that it can see individual characters as they are typed (this is usually called raw mode processing) and interpret them in whatever way it wants. C-d is recognized as EOF in canonical mode only, not in raw mode. See the man page referred to in the answer for more info. – NickD Jul 09 '17 at 02:05
  • 3
    @IgorLiferenko bash (and some other shells) have two different responses to ^D because they are trying to follow two different precedents: ancient shells without line editing ability behave just like cat, and exit on EOF, but editors like to use ^D for other purposes (like "delete character under cursor" in emacs). Interpreting the character as an exit command when it is typed on an empty line, and delete otherwise, is a compromise that works well (because you can't delete a character when there aren't any) –  Jul 09 '17 at 04:09