Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo

agnos.is Forums

  1. Home
  2. Linux
  3. Linux Terminal: CTRL+D is like pressing ENTER

Linux Terminal: CTRL+D is like pressing ENTER

Scheduled Pinned Locked Moved Linux
linux
20 Posts 11 Posters 0 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T [email protected]
    $ cat
    You sound very nice :)
    You sound very nice :)
    Bye<ctl-d>Bye
    
    Oh wait, and cool too
    Oh wait, and cool too
    <ctl-d>
    $ 
    

    The Ctl-D didn't end the file when i typed "Bye" 😞 it only worked when I pressed Ctl-D on its own line. So how does cat know that it should ignore the EOF character if there is some text that comes before it?

    What Ctl-D does is flush the input to the program, and the program sees how big that input is. If the length of the input is 0 that is interpreted as EOF. So Ctl-D is like Enter because they both flush the input, but Ctl-D is unlike Enter because it does not append a newline before flushing, and as a consequence you can send empty input (aka an EOF "character") with Ctl-D.

    ? Offline
    ? Offline
    Guest
    wrote on last edited by
    #10

    When running cat this way, you are in "cooked mode". A ctrl-d does nothing on a non-empty line.

    The shell usually runs in non-cokked, or raw, mode as well as nonblocking mode. Where it sees (nearly) every key you press as you press them. Which is why it " sees" the ctrl-d even when you are not on an empty line.

    You can learn more here:

    • https://jvns.ca/blog/2024/11/26/terminal-rules/#rule-3-repls-should-quit-when-you-press-ctrl-d-on-an-empty-line. (And more generally, from her various blog posts on the matter)
    • https://www.gnu.org/software/mit-scheme/documentation/stable/mit-scheme-ref/Terminal-Mode.html
    cypherpunks@lemmy.mlC T 2 Replies Last reply
    0
    • T [email protected]
      $ cat
      You sound very nice :)
      You sound very nice :)
      Bye<ctl-d>Bye
      
      Oh wait, and cool too
      Oh wait, and cool too
      <ctl-d>
      $ 
      

      The Ctl-D didn't end the file when i typed "Bye" 😞 it only worked when I pressed Ctl-D on its own line. So how does cat know that it should ignore the EOF character if there is some text that comes before it?

      What Ctl-D does is flush the input to the program, and the program sees how big that input is. If the length of the input is 0 that is interpreted as EOF. So Ctl-D is like Enter because they both flush the input, but Ctl-D is unlike Enter because it does not append a newline before flushing, and as a consequence you can send empty input (aka an EOF "character") with Ctl-D.

      S This user is from outside of this forum
      S This user is from outside of this forum
      [email protected]
      wrote on last edited by
      #11

      This!

      It's merely a buffer flush, in case it's empty, the program handling the input can choose how to interpret, cat decides to do it as an EOF.

      1 Reply Last reply
      0
      • T [email protected]

        Honestly I had no idea what ctrl+d even did, I just knew it was a convenient way for me to close all the REPL programs I use. The fact that it is similar to pressing enter really surprised me, so I wanted to share this knowledge with you 🙂

        M This user is from outside of this forum
        M This user is from outside of this forum
        [email protected]
        wrote on last edited by
        #12

        It’s not. You keep insisting that ^D doesn’t send EOF and yet:

        $ stty -a | grep eof
        intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
        $ man stty |grep -A1 eof |head -n2
               eof CHAR
                      CHAR will send an end of file (terminate the input)
        

        ^D is the EOF character. The thing is that in C every line of a text
        file must be terminated by a new-line. And so, when you end a file
        with ^D without a return, you get funky results.

        If you think ^D is like Enter, start a shell and without running a command press ^D.

        ferk@lemmy.mlF cypherpunks@lemmy.mlC 2 Replies Last reply
        0
        • M [email protected]

          It’s not. You keep insisting that ^D doesn’t send EOF and yet:

          $ stty -a | grep eof
          intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
          $ man stty |grep -A1 eof |head -n2
                 eof CHAR
                        CHAR will send an end of file (terminate the input)
          

          ^D is the EOF character. The thing is that in C every line of a text
          file must be terminated by a new-line. And so, when you end a file
          with ^D without a return, you get funky results.

          If you think ^D is like Enter, start a shell and without running a command press ^D.

          ferk@lemmy.mlF This user is from outside of this forum
          ferk@lemmy.mlF This user is from outside of this forum
          [email protected]
          wrote on last edited by
          #13

          To be more precise, it's the "EOT" (end of transmission) control character, the 4th symbol in ASCII, from the non-printable character area.

          1 Reply Last reply
          0
          • davel@lemmy.mlD [email protected]

            CTRL+M is like pressing enter. Kernigan & Pike, 1984: UNIX Programming Enviornment

            RETURN is an example of a control character — an invisible character that
            controls some aspect of input and output on the terminal. On any reasonable
            terminal, RETURN has a key of its own, but most control characters do not.
            Instead, they must be typed by holding down the CONTROL key, sometimes
            called CTL or CNTL or CTRL, then pressing another key, usually a letter. For
            example, RETURN may be typed by pressing the RETURN key or,
            equivalently, holding down the CONTROL key and typing an ‘m’. RETURN
            might therefore be called a control-m, which we will write as ctl-m.

            ferk@lemmy.mlF This user is from outside of this forum
            ferk@lemmy.mlF This user is from outside of this forum
            [email protected]
            wrote on last edited by
            #14

            Yes, ^M it's the "Carriage Return" (CR) character, /r, the 13th control character in ASCII.

            That's why if you open in Linux a Windows file in vim with Windows style EOL, you always see a strange ^M symbol at the end of each line.

            1 Reply Last reply
            0
            • T [email protected]

              Honestly I had no idea what ctrl+d even did, I just knew it was a convenient way for me to close all the REPL programs I use. The fact that it is similar to pressing enter really surprised me, so I wanted to share this knowledge with you 🙂

              M This user is from outside of this forum
              M This user is from outside of this forum
              [email protected]
              wrote on last edited by
              #15

              Lol wrong again

              1 Reply Last reply
              0
              • M [email protected]

                It’s not. You keep insisting that ^D doesn’t send EOF and yet:

                $ stty -a | grep eof
                intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
                $ man stty |grep -A1 eof |head -n2
                       eof CHAR
                              CHAR will send an end of file (terminate the input)
                

                ^D is the EOF character. The thing is that in C every line of a text
                file must be terminated by a new-line. And so, when you end a file
                with ^D without a return, you get funky results.

                If you think ^D is like Enter, start a shell and without running a command press ^D.

                cypherpunks@lemmy.mlC This user is from outside of this forum
                cypherpunks@lemmy.mlC This user is from outside of this forum
                [email protected]
                wrote on last edited by
                #16

                Note: for novices reading along at home, the notation ^X means hold down the ctrl key and type x (without shift).

                ctrl-a though ctrl-z will send ASCII characters 1 through 26, which are called control characters (because they're for controling things, and also because you can type them by holding down the control key).

                ^D is the EOF character.

                Nope, Chuck Testa: there is no EOF character. ^*^

                "D" being the fourth letter of the alphabet, sends ASCII character 4, which (as you can see in man ascii) is called EOT or "end of transmission".

                $ stty -a | grep eof
                intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
                $ man stty |grep -A1 eof |head -n2
                       eof CHAR
                              CHAR will send an end of file (terminate the input)
                

                What this means is that the character specified after eof (by default ^D, aka EOT) is configured to be intercepted (by the tty driver) and, instead of that character being sent to the process reading standard input, the kernel will "send an end of file (terminate the input)".

                ::: spoiler (*)
                One could also say there is an EOF character, but what it is can be configured on a per-tty basis.

                By default the EOF character is EOT, a control character, but it could be set to any character. For instance: run stty eof x and now, in that terminal, "x" (by itself, without the control key) will be the EOF character and will behave exactly as ^D did before.
                :::

                But "send an end of file" does not mean sending any character to the reading process: as the blog post explains, it actually (counterintuitively) means flushing the buffer - meaning, causing the read syscall to return with whatever is in the buffer currently.

                It is confusing that this functionality is called eof, and the stty man page description of it is even more so, given that it (really!) does actually flush the contents of the buffer to read - even if the line buffer is not empty, in which case it is not actually indicating end-of-file!

                You can confirm this is happening by running cat and typing a few characters and then hitting ^D. (cat will echo those characters, even though you have not hit enter yet.)

                Or, you can pipe cat into pv and see that ^D also causes pv to receive the buffer contents prior to hitting enter.

                I guess unix calls this eof because this function is most often used to flush an empty buffer, which is how you "send an end of file" to the reader.

                Anyway, the empty-read-means-EOF semantics are documented, among other places, in the man page for the read() syscall (man read😞

                On success, the number of bytes read is returned (zero indicates end of file)

                If you want ^D to send an actual EOT character through to the reading process, you can escape it using the confusingly-named lnext function, which by default triggered by the ^V control character (aka SYN, "synchronous idle", ASCII character 22 - note V is the 22nd letter of the alphabet):

                $ man stty|grep lnext -A1
                       * lnext CHAR
                              CHAR will enter the next character quoted
                $ stty -a|grep lnext
                werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
                

                Try it: you can type echo " and then ^V and ^D and then "|xxd (and then enter) and you will see that this is sending ascii character 4.

                You can also send it with echo -e '\x04'. Note that the EOT character does not terminate bash:

                $ echo -e '\x04\necho see?'|xxd
                00000000: 040a 6563 686f 2073 6565 3f0a            ..echo see?.
                $ echo -e '\x04\necho see?'|bash
                bash: line 1: $'\004': command not found
                see?
                

                As you can see, it instead interprets it as a command.

                ::: spoiler (Control characters are perfectly cromulent filenames btw...)

                $ echo -e '#!/bin/bash\necho lmao' > ~/.local/bin/$(echo -en '\x04')
                $ chmod +x ~/.local/bin/$(echo -en '\x04')
                $ echo -e '\x04\necho see?'|bash
                lmao
                see?
                

                :::

                Anyway, hopefully this all convinces you that EOF is not a character 🙂

                M 1 Reply Last reply
                0
                • ? Guest

                  When running cat this way, you are in "cooked mode". A ctrl-d does nothing on a non-empty line.

                  The shell usually runs in non-cokked, or raw, mode as well as nonblocking mode. Where it sees (nearly) every key you press as you press them. Which is why it " sees" the ctrl-d even when you are not on an empty line.

                  You can learn more here:

                  • https://jvns.ca/blog/2024/11/26/terminal-rules/#rule-3-repls-should-quit-when-you-press-ctrl-d-on-an-empty-line. (And more generally, from her various blog posts on the matter)
                  • https://www.gnu.org/software/mit-scheme/documentation/stable/mit-scheme-ref/Terminal-Mode.html
                  cypherpunks@lemmy.mlC This user is from outside of this forum
                  cypherpunks@lemmy.mlC This user is from outside of this forum
                  [email protected]
                  wrote on last edited by
                  #17

                  A ctrl-d does nothing on a non-empty line.

                  ctrl-d actually is flushing the buffer regardless of if the line is empty or not.

                  See my other comment for how you can observe it.

                  1 Reply Last reply
                  0
                  • cypherpunks@lemmy.mlC [email protected]

                    Note: for novices reading along at home, the notation ^X means hold down the ctrl key and type x (without shift).

                    ctrl-a though ctrl-z will send ASCII characters 1 through 26, which are called control characters (because they're for controling things, and also because you can type them by holding down the control key).

                    ^D is the EOF character.

                    Nope, Chuck Testa: there is no EOF character. ^*^

                    "D" being the fourth letter of the alphabet, sends ASCII character 4, which (as you can see in man ascii) is called EOT or "end of transmission".

                    $ stty -a | grep eof
                    intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
                    $ man stty |grep -A1 eof |head -n2
                           eof CHAR
                                  CHAR will send an end of file (terminate the input)
                    

                    What this means is that the character specified after eof (by default ^D, aka EOT) is configured to be intercepted (by the tty driver) and, instead of that character being sent to the process reading standard input, the kernel will "send an end of file (terminate the input)".

                    ::: spoiler (*)
                    One could also say there is an EOF character, but what it is can be configured on a per-tty basis.

                    By default the EOF character is EOT, a control character, but it could be set to any character. For instance: run stty eof x and now, in that terminal, "x" (by itself, without the control key) will be the EOF character and will behave exactly as ^D did before.
                    :::

                    But "send an end of file" does not mean sending any character to the reading process: as the blog post explains, it actually (counterintuitively) means flushing the buffer - meaning, causing the read syscall to return with whatever is in the buffer currently.

                    It is confusing that this functionality is called eof, and the stty man page description of it is even more so, given that it (really!) does actually flush the contents of the buffer to read - even if the line buffer is not empty, in which case it is not actually indicating end-of-file!

                    You can confirm this is happening by running cat and typing a few characters and then hitting ^D. (cat will echo those characters, even though you have not hit enter yet.)

                    Or, you can pipe cat into pv and see that ^D also causes pv to receive the buffer contents prior to hitting enter.

                    I guess unix calls this eof because this function is most often used to flush an empty buffer, which is how you "send an end of file" to the reader.

                    Anyway, the empty-read-means-EOF semantics are documented, among other places, in the man page for the read() syscall (man read😞

                    On success, the number of bytes read is returned (zero indicates end of file)

                    If you want ^D to send an actual EOT character through to the reading process, you can escape it using the confusingly-named lnext function, which by default triggered by the ^V control character (aka SYN, "synchronous idle", ASCII character 22 - note V is the 22nd letter of the alphabet):

                    $ man stty|grep lnext -A1
                           * lnext CHAR
                                  CHAR will enter the next character quoted
                    $ stty -a|grep lnext
                    werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
                    

                    Try it: you can type echo " and then ^V and ^D and then "|xxd (and then enter) and you will see that this is sending ascii character 4.

                    You can also send it with echo -e '\x04'. Note that the EOT character does not terminate bash:

                    $ echo -e '\x04\necho see?'|xxd
                    00000000: 040a 6563 686f 2073 6565 3f0a            ..echo see?.
                    $ echo -e '\x04\necho see?'|bash
                    bash: line 1: $'\004': command not found
                    see?
                    

                    As you can see, it instead interprets it as a command.

                    ::: spoiler (Control characters are perfectly cromulent filenames btw...)

                    $ echo -e '#!/bin/bash\necho lmao' > ~/.local/bin/$(echo -en '\x04')
                    $ chmod +x ~/.local/bin/$(echo -en '\x04')
                    $ echo -e '\x04\necho see?'|bash
                    lmao
                    see?
                    

                    :::

                    Anyway, hopefully this all convinces you that EOF is not a character 🙂

                    M This user is from outside of this forum
                    M This user is from outside of this forum
                    [email protected]
                    wrote on last edited by
                    #18

                    Which is why I haven’t wrote ‘EOF character’, ‘EOT’ or ‘EOT character’. Neither have I claimed that \x4 character is interpreted by the shell as end of file.

                    1 Reply Last reply
                    0
                    • ? Guest

                      When running cat this way, you are in "cooked mode". A ctrl-d does nothing on a non-empty line.

                      The shell usually runs in non-cokked, or raw, mode as well as nonblocking mode. Where it sees (nearly) every key you press as you press them. Which is why it " sees" the ctrl-d even when you are not on an empty line.

                      You can learn more here:

                      • https://jvns.ca/blog/2024/11/26/terminal-rules/#rule-3-repls-should-quit-when-you-press-ctrl-d-on-an-empty-line. (And more generally, from her various blog posts on the matter)
                      • https://www.gnu.org/software/mit-scheme/documentation/stable/mit-scheme-ref/Terminal-Mode.html
                      T This user is from outside of this forum
                      T This user is from outside of this forum
                      [email protected]
                      wrote on last edited by
                      #19

                      Interesting, I have not heard of these terms before. Thanks for sharing!

                      I think this adds the bit of nuance that was bugging me: using something like ncurses or vim, presumably when you press a key like ctrl-z or ctrl-d it actually sends the character to the app. It would feel a bit silly if the terminal intercepted the ctrl-d, flushed some buffer, and the program had to reverse engineer whether you pressed ctrl-d or enter or something.

                      For raw mode, I assume the app asks the tty to please forward some characters to the app. Otherwise, in the default cooked mode, the tty intercepts those control characters to call certain functions. I suppose some REPLs may choose to emulate a cooked mode on top of raw mode, and so they have to handle the \x04 in the same way a tty would to keep it functioning like the user expects. I believe readline does something like this, which is why you had to use bash --noediting for ctrl-d to run the command. Good food for thought 🙂

                      I also have to say, naming it "cooked mode" is extremely funny as gen z. I love that

                      1 Reply Last reply
                      0
                      • R [email protected]

                        For some reason my mobile client didn't make the article link immediately obvious. That's actually really interesting. Apparently I was under the same common misconception. So the shell in this case is choosing to continue after detecting the flush.

                        T This user is from outside of this forum
                        T This user is from outside of this forum
                        [email protected]
                        wrote on last edited by
                        #20

                        Ohh I gotcha. Honestly no sweat, its kind of just a bit of fun trivia really 🙂

                        1 Reply Last reply
                        0
                        • System shared this topic on
                        Reply
                        • Reply as topic
                        Log in to reply
                        • Oldest to Newest
                        • Newest to Oldest
                        • Most Votes


                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • World
                        • Users
                        • Groups