Terminal – Using Ctrl+D to End Line Input

catcommand lineterminal

If I do

$ cat > file.txt

textCtrlDCtrlD

Question 1: If I don't press enter, why do I have to press CtrlD twice?

If I do

$ cat > file.txt

pa bam pshhhCtrlZ

[2]+  Stopped         cat > file.txt
$ cat file.txt
$ cat > file.txt

pa bam pshhh

CtrlZ

[2]+  Stopped         cat > file.txt
$ cat file.txt
pa bam pshhh

Why is the second time the file with 1 line?

Best Answer

In Unix, most objects you can read and write - ordinary files, pipes, terminals, raw disk drives - are all made to resemble files.

A program like cat reads from its standard input like this:

n = read(0, buffer, 512);

which asks for 512 bytes. n is the number of bytes actually read, or -1 if there's an error.

If you did this repeatedly with an ordinary file, you'd get a bunch of 512-byte reads, then a somewhat shorter read at the tail end of the file, then 0 if you tried to read past the end of the file. So, cat will run until n is <= 0.

Reading from a terminal is slightly different. After you type in a line, terminated by the Enter key, read returns just that line.

There are a few special characters you can type. One is Ctrl-D. When you type this, the operating system sends all of the current line that you've typed (but not the Ctrl-D itself) to the program doing the read. And here's the serendipitous thing: if Ctrl-D is the first character on the line, the program is sent a line of length 0 - just like the program would see if it just got to the end of an ordinary file. cat doesn't need to do anything differently, whether it's reading from an ordinary file or a terminal.

Another special character is Ctrl-Z. When you type it, anywhere in a line, the operating system discards whatever you've typed up until that point and sends a SIGTSTP signal to the program, which normally stops (pauses) it and returns control to the shell.

So in your example

$ cat > file.txt
pa bam pshhh<Ctrl+Z>
[2]+  Stopped         cat > file.txt

you typed some characters that were discarded, then cat was stopped without having written anything to its output file.

$ cat > file.txt
pa bam pshhh
<Ctrl+Z>
[2]+  Stopped         cat > file.txt

you typed in one line, which cat read and wrote to its output file, and then the Ctrl-Z stopped cat.

Related Question