Hacker News new | past | comments | ask | show | jobs | submit login
What typing ^D does on Unix (2009) (utcc.utoronto.ca)
536 points by luu on Sept 6, 2016 | hide | past | favorite | 156 comments



As a corollary, typing ^D twice on a non-empty line will also send EOF on the input, allowing you to provide a program with input not ending with \n from the command line. I knew about this behavior, but not why it worked, but this article's explanation clarifies this behavior as well. The first ^D terminates the read() call, passing the line so far, without terminating \n, to the program. The second causes read() to return with 0 read bytes, which is EOF, as explained in the article.


A super easy way to see this is to type cat, and then type asdf and hit ^D. It immediately echoes back what you typed. Another ^D quits cat, because it gets a 0-byte read that time.


This was cool. Thanks for sharing!


I asked about this on StackOverflow a few years ago, and got a great answer.

http://stackoverflow.com/questions/15666923/sys-stdin-does-n...


...and i remember answering a similar question on SO.

http://stackoverflow.com/a/35537499/319204


I know this article says Unix specifically, but on Linux (Ubuntu) I just tried typing `ls^D` in bash and got a terminal beep. I tried in zsh and got an autocomplete as if I'd hit tab. In ksh and fish nothing happened. I'm curious as to why there are different behaviors here?


I believe your answer is in the article: "Note that modern shells are not good examples of this, because they don't do line-buffered input; to support command line editing, they switch terminal input into an uninterpreted mode. So they get the raw ^D and can do whatever they want with it, and they can let you edit as much of the pending line as they want."


As the article explained at the end, shells put the terminal into uninterpreted mode, so ^D doesn't do anything special there. You have to be using a program (such as cat) that doesn't do this to see ^D's behavior.


Actually bash (by default) does do something special with ^D: it's mapped to the "delete-the-char-after-the-cursor" functionality (just like the DEL key is), by analog to the delete-char binding in emacs.

But indeed, it's in raw mode so the kernel doesn't do anything special and just emits the 0x04 byte down the descriptor.


Shells that want to implement features like tab completion or more elaborate line editing than the basics, which only provide for deleting the last character, word, or line (using Backspace/^W/^U) need to put the terminal into raw mode when reading the user's command line so they can bypass the basic line editing that the terminal provides (called "cooked mode").

However, you can write a shell that doesn't do this. In particular, on Linux, you can experiment in dash. You'll find that the behavior is exactly the same as this article, since the terminal remains in cooked mode. In particular, if you type `l^Ds`, that will run `ls`, though you won't be able to delete the `l` anymore since that was input before the `^D`. Also, if you type `ls^D^D`, that will log out just like typing `^D` on an empty line does. Other shells have different behaviors -- for example, Bash seems to take `ls^D` to be the same as typing `ls` followed by pressing Enter.

Before any shell starts executing a program, however, it puts the terminal back in cooked mode no matter what mode it's in when at the prompt, since that's the default terminal mode expected by programs. If you want to experiment with the cooked mode line editing commands to get the behavior described in the article, you should run a command that receives standard input from the terminal (running `cat` by itself should suffice).


I didn't realize Dash uses cooked mode. That's actually kind of surprising; every other shell I've used always uses raw mode to give them more control over line editing. Is Dash just trying to be as minimalistic as possible?


Dash is really minimalistic. In its default mode, this is the only call to ioctl it makes on standard input according to strace:

    ioctl(0, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
Notice that it's merely calling TCGETS and that icanon is set, which means the "canonical input" mode with the default ^W/^U keybindings is enabled. Bash disables icanon so that it can enable line editing. Interestingly, dash seems to have vi and emacs editing modes, but they don't seem to cause dash to enter raw mode, so I'm not sure they do anything.


No TTY-related discussion is complete without a reference to Linus Akesson's extremely lucid article on the whole thing, including what all the other interesting Ctrl+ characters do:

http://www.linusakesson.net/programming/tty/

...and the extensive previous HN discussion on it:

https://news.ycombinator.com/item?id=10631513

https://news.ycombinator.com/item?id=10064657

https://news.ycombinator.com/item?id=8094186

https://news.ycombinator.com/item?id=4544318

https://news.ycombinator.com/item?id=4062981

https://news.ycombinator.com/item?id=658155


^U will clear the buffer - super convenient for retrying botched passwords.


Fun trick: If somebody is watching you type in your login password or SSH pubkey password, spaz wildly on the keyboard, frantically typing random characters, and then hit ^U and type in your real password.

Then you give them a puzzled look once you successfully log in as if nothing out of the ordinary just happened and say something like "What, don't you have a sufficiently complex password?".


> "What, don't you have a sufficiently complex password?"

<anecdote> I actually had a sufficiently complex password, but this one time I was in a massive hurry to demo something to my teammates, I made a mistake somewhere near the end of it, quickly typed ^U, fed it all over again, made another mistake near the end, another quick ^U, and third time was the charm.

They didn't notice that I reset the password field twice, to them it was just a mega-super-duper-long password (the actual password is 20+ characters), and one of them burst out saying, "Woah! He just wrote a short story!" </anecdote>


As long as you don't hit space you can do the same thing with ^W, as ^W will clear out the last 'word'. I use it all the time at password prompts, and more comfortable to hit than ^U.


It's easier if you switch Ctrl and Caps because they n it just looks like you're just using the shift key.


I would like to recommend against spazing wildly at work.

Edit: It was just a joke :(


In readline, ^U will only clear from the cursor to the start of the line, leaving anything on the right. ^K is the converse.

I'm not sure you are speaking about readline though.

Another very useful thing I use daily is Alt-F/B, to move forward/backward in the line one word at a time. Control does the same, one letter at a time. D will delete an element instead.


There's a lot of unexpected gems in the readline defaults. I recommend people try paging through "bind -p" in bash some time to see what's there.

Personal favorites are C-r to search back in history and C-x C-e to edit the current command line in an external editor.


Emacs users will recognize many of the readline defaults -- unsurprisingly, given both are GNU software.

I use "yank-last-arg" most often, which is M-. by default.

  $ mkdir abcd
  $ cd <M-.>
On Zsh, I have M-, bound to "copy-earlier-word", which makes M-. M-, M-, cycle through the arguments to the previous command.

In reading the manpage for Bash, which doesn't have this function, I've just found "history-search-backward", which searches through history to find commands based on what you've already typed. That will come in useful!

  $ bind '"\er":history-search-backward'
  $ bind <M-r>
(Note that M-r is bound to "revert-line" by default, but I doubt I'll use that.)

These functions are all listed, with explanations, in the Bash and Zsh manpages.

Edit: As I see from another comment, a binding for "history-search-backward" to the Page Up key is in /etc/inputrc on Debian and derivatives.


It is also very convenient to remap up/down keys to not just list history, but to do completion based on already typed characters:

    if [[ $- == *i* ]]
    then
        bind '"\e[A": history-search-backward'
        bind '"\e[B": history-search-forward'
    fi
(fix: grammar)


Debian and Ubuntu typically have a commented-out mapping for this in /etc/inputrc as pgup/pgdn that I always enable in my ~/.inputrc. Editline supports something similar in .editrc IIRC.


Funny, I became FreeBSD user because default .cshrc contained it (iirc). I didn't know about shells, readline, etc. back then. Wonder why they do not enable it on up-down by default, cause I see too many linuxoids around bored with up-up-up-enter up-up-up-enter to replay history, not even knowing that completion exists (along with at least ^K ^U ^C).

What's the point to type a half-command and then replace input line with one from history if I press up? That somewhat resembles ugly cmd.exe, which every windows user imagines when someone says 'cli'.


Weird, I'd have thought C-r is the one readline command everybody knows even if they know nothing else abour readline. Almost cannot imagine using command line without it. (Though there's also the "like tab-complete but from history" that I never really learned to use.)


Ah! yes, at this point C-r is so entrenched in my habit, I didnt even realize it might be new to some.

This is the shortcut to first learn when starting living in the command line.


Yes some of these useful functions should be bound by default IMHO. Here are my settings to bind ctrl-{left,right} and {up,down} to more useful defaults. I.E. jump as the shell tokenizes the line, and search history for what's already typed respectively


For the vi-adherents out there, `set -o vi` will let you navigate your prompt and history with vi-like keybindings. I'm amazed by how many vi users don't know this.


I'm amazed by how many people still run bash!


Why wouldn't they it is one of the defacto standards? You use what you know most of the time.


¯\_(ツ)_/¯


To add to that, C-P will go up in your history and C-N down. It is extra useful when using GDB in TUI mode (which is activated using C-x,a), which will capture your UP/DOWN arrow to navigate the source...

Actually, just go read http://ss64.com/bash/syntax-keyboard.html or something, once per day, integrate a new one each time, and you will improve your productivity on the command line (as well as comfort).


For gdb TUI, you can also use the 'focus cmd' and 'focus src' commands to choose which window gets to handle up/down. I usually keep the command window focused out of habit because the source window intercepts too many keys for my liking.

Nice link - reminds me to try to use the history stuff like ! and ^ more.


I also find Ctrl-W for backspacing a word at a time useful and also Ctrl-A/E for jumping to the beginning and end of the current line.

Ctrl-L to clear the screen except the current line is also somewhat useful if you're at the bottom of the terminal screen and editing a long command line.

Somewhat less useful but neat is Alt-U which will cause the current word under the cursor to become all upper case and Alt-C which is similar but changes the first letter to upper case and the rest of the word to lower case.


^Y will paste the cleared buffer back again


So ^U will let a partial password linger in memory longer than it needs to if you use it as suggested by the GP?


To elaborate on yebyen's answer: these shortcuts can be handled in different layers of your stack. By default, ^U will be handled by your terminal emulator, and it will only delete the buffer, it won't remember what you've deleted. However, programs can ask the terminal emulator to pass ^U through to them so they can handle it themselves. This happens if you use libeditline (or libreadline), and these libraries implement a per-application buffer.

You can test this yourself. Type some text, then ^U, then ^Y. This works because your shell uses libreadline or libeditline. Try this again in a "dumb" program like cat, or a shell without line editing like /bin/dash. ^U works, but ^Y does nothing (well, it lets you type ^Y in as much as you want).


Actually, NAK in canonical mode is handled by the line discipline in the pseudo terminal device rather than by the emulator.


No, I don't think so. Not unless you are accustomed to typing your password directly into the terminal prompt. Kill buffers don't pass from one application to another and they don't all behave the same in every context, either.

(For example, if I type some stuff and then ^U to kill the password buffer at an SSH password prompt, typing ^Y after that seems to put the whole process in the background. Not sure what that's intended to do, but subsequent ^Y presses don't retrieve the password into the shell prompt...)


In canonical mode, EM is the usual "delayed suspend" special character.


Actually, this is a feature of libreadline (in its default configuration). ^Y mimics the yank command from emacs. At an actual terminal input (like you can get by running `cat` with no arguments), ^Y will just echo back a literal ^Y (assuming it too is in its default configuration).


Something I use extensively in terminals is ^L and ^M. ^L clear the screen and ^M for a line return.


May I ask why you find more convenient to press ^M for a line return instead of the line return key?


As someone else who also uses ^M for line return here's my reason.

I have the Caps key mapped to control, so ^M is 2 small finger movements as opposed to reaching for the return key which means either moving my (weak in my case) right wrist or moving my whole right forearm. It's a small movement to the return key but I find eliminating it really helps to reduce strain related pain when typing.

I also use ^H for backspace and ^I for tab for similar reasons. This also keeps my fingers on the home row.


I'm not proud of this, but I sometimes bounce between ^N (next-line in emacs) and ^I (tab character, bound to various thing in different emacs modes) to re-indent a region. I usually only do this for <10 lines. More than that and I go look up the function that does it 'right'.


Why not proud? Sounds fast and efficient. I didn't save the move of the hand to the tab key, but I will now. Thanks.


^U is actually very convenient for clearing the current line when using the default mysql client. Still sometimes find myself at the command prompt after ^C because I'm used to psql.


Is ^U same as ALT+Backspace? I use this for deleting passwords. But only works for specific shell/ssh/OS.


Typing +++ will bring you back out to your modem's firmware, at which point you can issue further AT commands


+++ATH0


Darnit, I had to dial in again.

Kidding of course, but once upon a time many 56k6 modem contained a bug that, upon receiving this in plain text, would cause an actual modem hangup. You could kill hundreds of IRC connections with that one.


It wasn't exactly an unintentional bug - rather one company owned a patent on the technique of enforcing a guard time before and after the attention string to go into command mode (the Hayes '302 patent). They licensed it for $1/modem, but some manufacturers felt that they couldn't afford that.


Ha, I never knew! Thanks for adding this; who would have thought my 20 year old anekdote would get a refreshment. :-)


How did modems deal with pluses in data? Was there a way to escape the escape sequence, or was there just an ATSnnn or similar sequence to disable escapes?


There were a bunch of different mechanisms depending on vendor. Some required a specific time interval in between the + signs, so that typing very slowly, or instantly, wouldn't trigger the escape.

Some vendors had bugs in which when +++ appeared as part of the incoming data it would also trigger the firmware escape.

And of course programmable terminals had hilarious exploits where you'd get someone to run your program, it would program the terminal to emit a macro when you hit enter, the macro would include +++ATZ, etc., etc.

My favorite modem story was when I worked for a company that shipped auto parts warehouse management systems. They would have several SCO unix boxes with serial port concentrator cards and port concentrators on those concentrators, such that you'd have 256 modems on a single box and RS-232 cables everywhere. Frequently the operators at the auto parts warehouses couldn't be bothered to do cable management, so at one facility, the entire floor of the server closet was carpeted literally 2 feet thick with a random mess of RS-232 cables, each one leading to a modem. When standing on the cables killed a modem or two, they would just string a new wire rather than try to fish out the old one. Kind of like Google's "let it sit in the rack" policy for failed servers, but writ extremely small and pathologically badly.


> "let it sit in the rack"

So do they do scheduled collections of failed units? Or just let them sit there indefinitely?


The entire rack gets replaced with new equipment eventually. Probably get replaced every few years or so.

For most of the SMB clients I have, I don't build new servers any longer. I can buy rackmount servers pulled out of a data center that are a few years old at about 1/3 the price. I just put new disks in them and a new OS.


How did modems deal with pluses in data?

Many years ago, modem maker Hayes Microcomputer Products held a patent dealing with that issue. The clever bit was in looking for

   <pause> +++ <pause>
to effect the escape.

Hayes tried to collect royalties, but this caused quite a kerfuffle. Cheap modem makers didn't bother looking for pauses. "Hilarity" ensued. Other solutions were found.

https://en.wikipedia.org/wiki/Time_Independent_Escape_Sequen...


OK


Thank you for this blast from the past :)


The author actually clouds what and why is really happening a bit. Ctrl+D sends the EOF character to the terminal driver. The terminal driver then determines, based on its settings, what to do next.

In the 'icanon' mode, the terminal driver implements a rustic line editor, so you can do things like Backspace to delete previous characters and so on. Pressing Enter during this mode returns the edited buffer line to the program.

Where Ctrl+D, or EOF, comes in is when you want to return a line to the program _without_ pressing Enter. This is where the terminal driver returns the buffer to the read() function for the program immediately. Doing it again with no additional input shows that you were done line-editing, so it simply returns nothing, signaling the program that you're done editing or providing input - the intended purpose of End Of File, the character sent by Ctrl+D. (If you were reading a file and you received nothing on a read... you would be at the end of a file, because why else would the file have nothing else to read?)

But this 'icanon' mode won't be active in your actual terminal shell, because shells have their own line editing implementation, so they turn 'icanon' off by default. You can, of course, turn on or off in the terminal with "stty". Use "stty -a" to see all the other current settings. The terminal application, by the way, sets the EOF to the same value as the terminal driver's by default, in order to prevent confusion.


Directly after reading the title the question "what does ^D do" was fired at a Old Unix Beard friend of Mine who happens to be here for coffee.

Instant reply Without any latency: "It originally was meant to terminate the Tape drive"


[citation needed] I suspect they're misremembering what the T in EOT stands for.



Pressing enter then ~. will gracefully shutdown hung ssh sessions


More generally, type ~ as an escape sequence.

For example, type ~^Z to put a session in the background.

Similarly, type ~~ to send an escape sequence in an inner session, etc...


...

  There's a program called SSH to get to another CPU.
  Tilde is the escape, it's doubled to send it through,
  And "quit" is tilde-.
I think you know how the rest goes...


I don't - and in fact I finally got around to creating a HN account in order to ask you. Googling that just leads me back to this discussion. What's it from?


It's parodying "the TELNET song," by Guy L. Steele.


For more information: http://wonderingminstrels.blogspot.com/2004/01/telnet-song-g...

If you have an ACM subscription, the sheet music was published in Communications of the ACM (Volume 27, Issue 4; April 1984): http://dl.acm.org/citation.cfm?id=1035691


What does this reference?


It references "The TELNET Song" by Guy L. Steele (a.k.a The Great Quux). The original is about Telnet, and given the subject of discussion, the reference seemed a natural one to make.


I am not sure, but it looks vaguely familiar. There is a text-based game called adventure game called Dunnet where you come across a CPU card, and do some stuff with it later on. As far as I remember, the game predates SSH, so the game either had Telnet or FTP. My memory fades.


Or type ~? for a list of escapes.


I am amazed by the fact that I never accidentally trigger this feature.


Hah, yeah I seem to remember Ctrl-S leaving me flustered for quite a while when I first stumbled on it!


^-Q is your friend!


You'd probably trigger it more often if ~/ didn't conveniently map to ~/ - it's quite cleverly designed in a way. Indeed, most of the two-character combinations you're likely to type starting with ~ map to themselves.


It's annoying when you're adminning users and atually want to type "~user/foo" though.


Yes, it's a good choice of characters.

Specifically, the escape sequence is "\n~", with various options (visible by typing "\n~?"), and if the option is unknown it passes the "\n~{x}" as-is.

The biggest false positive you'll see is "\n~v", when executing bins out of the home dir of a user starting with the letter 'v'.


Sadly it will shutdown only the 'outer' ssh session, so if you ssh to foo, and then from foo ssh to bar, and type ~. then the client->foo session is shut down but the foo->bar session is still around.


You need to type one ~ per session level toy want to reach and terminate. In your example, type ~~. to terminate the inner session, leaving the outer one live.


To kill the inner one you need to escape it: ~~. ~? displays the supported escape sequences.


nice one, never seen that - always used ^D/exit


Those are yet more graceful -- for when the shell is responsive. Use ~. in cases where for some reason you cannot get access to the terminal anymore but remote sshd is responsive.


Actually the remote sshd does not need to be responsive, because "<cr>~." is interpreted by the local ssh client. Very convenient if the TCP connection is stuck.

You can also type "<cr>~?" for a list of other commands supported by the local ssh client. Among other things, "<cr>~C" opens a command line interpreter on the client side of the ssh client, allowing you to add and remove TCP port forwarding without restarting the connection.


Ahg, I wish it let you scp files into your working directory too. That's be convenient.


Long ago I sent a patch for uploading downloading using this escape sequence, using zmodem like how an old windows SSH client (I forget the name) used to allow uploading/downloading files.

You log in, type "rz<enter>", and then use escape sequence to upload a file. (similar for downloading)

The patch was rejected. Shame. It's very useful when hopping 6 steps to upload a file.[1]

I can't find the patch now, but I'm considering rewriting it as a an `expect` script. My `expect` scripts tend to have trouble with SIGWINCH propagation though, so not optimal. Also you have to remember to wrap with the `expect` script at (and preferably only at) the one "jump" you want to send from/to with the final destination.

[1] No, nothing illegal. Just that some networks mandate SSH jumpgates, and sometimes multi-level.


~. (and the other ~ commands) are handled locally, not by the remote sshd. I use it when my network cuts out or something and my ssh session is unrecoverably stuck


You can also layer the number of ~'s to skip over intermediary SSH sessions and send the escape to the proper one.

\n~~. will escape the 2nd box you've SSH'd to, not the one it was originated from.

Useful for escaping a screen'd SSH session that you might access through a jumphost.


iirc, enter-~-. isn't anything to do with the remote sshd. Instead, it escapes to the local ssh client (enter-~) that it should close (.). Which is really useful for if the remote sshd blew up, or, more commonly, your connection was broken.


6 KB HTML. 4 KB CSS with comments preserved. No JS.

It's so beautiful. I think I'm going to cry :)


In general, CTRL-anything send corresponding control character by shifting keys to control set of ASCII table [1] (shift-key shifts keys to upper set). Many of them retained original meaning, e.g. ^I ^M ^J ^H ^D ^[.

[1] http://ascii-table.com/


I wish articles like this would say what ^D means. I remember when I was new to Unix it took me a while to realize that I wasn't supposed to type a literal caret (^) followed by a D.

For reference it means Ctrl+D, unless you you have a strange keyboard from Sun or something.


^D is the old school way of writing it; you'd see it so much you'd only ever once be confused about it, generally in the very first few days you were learning to use a computer.

It's never used anymore, I suppose, except for the old school people who still have enough muscular memory built up to write it that way. I know I do; I learned it from some computer magazine in the 80's and have a hard time letting go.


I dunno if I'd say it was never used anymore. Try running `cat` (to bring up a basic termainal input) and type various control keys. Anything that isn't interpreted by the tty is probably displayed using caret notation.


> It's never used anymore, I suppose, except for the old school people who still have enough muscular memory built up to write it that way. I know I do; I learned it from some computer magazine in the 80's and have a hard time letting go.

I was born after the 80s, and I use that shorthand (although I suppose this probably says more about me than it does about the shorthand itself). I didn't even understand the original comment until I read through the whole thing because I mentally read it as "Ctrl+D"


It's used when talking about text editors a fair bit.


More than just text editors, it is used system wide in OS X menus to describe the available shortcuts.


I just tried to search for it as if I didn't know and it was hard. Maybe wikipedia should describe that ^ is common representation among first lines, not in details section. Also macOS (former osx) uses this symbol everywhere: http://www.macinstruct.com/images/command.png


Yes, but it is so annoying and confusing that these symbols are not printed on the actual keyboard. Looking at the keyboard doesn't help much when I try to press a shortcut I just saw in the menu.


Reminds me of how many time I went crazy trying to close a telnet session on memcached ("Escape character is '^]'.") :)


And then imagine trying to escape telnet on an international keyboard (Swedish in my case). Telnet actually kind of works, if you press ctrl+altgr+8 (which is one hell of a hand-twister), but many games and GUIs ONLY allow you to press the listed, with no other modifiers.

So many games don't even allow you to open the console, because they assume that your key next to 1 is ~, and so don't work for § (next to 1) or altgr+¨ (the layout's ~). Or switch between looking at characters or scancodes depending on the context, and thus work in some cases but not all.


^D, Ctrl+D and C-d are all different ways of saying the same thing. There's nothing particularly neutral about Ctrl+D, any more than there is about using the word 'water' to mean the substance of which the oceans are mostly comprised — it's just another dialect's term.


The button on the keyboard literally says "control" or "ctrl" on it. How could that possibly not be easier to figure out than "^" or "C-"?


Look at the confusion that surrounds "Strg" for this very same key.

Also note that on some keyboards it has the U+2638 character engraved.


C stands for control.


The same argument you made could be used if the author used the unicode codes for Ctrl+D, which I find to be an indication that the argument was a bit weak. The article itself is written in English, and to expand upon your metaphor, tt would be strange to use the term agua to refer to water in an English article. Language is really based around what people use, so using what people know is generally considered good communication. If you use something different it's considered good form to explain why. Each representation you chose is effectively shorthand for the English phrase 'Control + D', just with different stylistic representations. People are much more familiar with Ctrl+D to refer to the key combination of Control and D.

Anyways, I had the same issue when I first started using Linux. It probably took me over a year to realize the caret stood for ctrl, and that's only because I accidentally typed it in something that printed the codes literally.


It's not about neutrality, it's about ease of understanding. For me at least, when speaking about something that can be entered into a keyboard ^D is less obvious than Ctrl+D–I need to press the key labeled "control" to issue the proper command, the key labeled "^" will not suffice.


To be really pedantic (sorry! I'm not complaining about your comment), your keyboard does not have any key labelled 'control', it is always (AFAIK) abbreviated as 'ctrl'. Which is really weird to me, as it's hardly a big word needing abbreviating, and keyboards often have other long words written on the keys ('delete', 'page down', and so on).

On top of that, the shortened 'ctrl' is really a terrible abbreviation. It's not obvious that it stands for 'control' and I would guess that most non-techy people would have no idea that it means this word. Plus, it's near to another key with multiple letters ('alt'). The overall effect is that 'ctrl' appears to just be a jumble of letters with some esoteric meaning. A really odd design decision. Why not just put 'control' on the key and be done with it?


You're incorrect, especially for the typical reader here. A good chunk (maybe not over 50%, but its gotta be close) of the regular readers on this site use Macs. Most Mac keyboards, including the ones on the Macbook Pro, spell it out. Same for most non IBM/IBM-PC compatible keyboards.


I'm typing on a MacBook Pro that has "ctrl".

Not sure I've ever seen a Mac keyboard that said "control", but maybe that's because I've mostly seen Finnish keycaps.


Enjoy this picture of an Apple keyboard that says "control": https://commons.wikimedia.org/wiki/File:Apple_Keyboard.JPG


Look in the menu bars and you'll only see ^ describing the shortcuts.


I'm typing on a mac keyboard too. It has 'ctrl', 'esc', but 'delete' is written in full.


My mid 2014 MBP control key is labeled "control"



How odd! My mac keyboard is a similar design, but has 'ctrl', and has no writing on the shift keys, caps lock and so on. The only unabbreviated word it has is 'delete'.

Perhaps the standard is something to do with the country (mine is a UK layout).


Yes, it does. Not sure why, but:

http://i.imgur.com/vvQNuQX.jpg


Even then though, why is it obvious that you don't need to press the key labelled + as well?


All I know is that in my youth ^ sent me to google befuddled a few times while + never did


But Ctrl is easier to figure out from context, since it's a multi-character Googlable symbol that's even printed on the key.


> ^D, Ctrl+D and C-d are all different ways of saying the same thing.

Right, and the classic book The Unix Programming Environment (by Brian Kernighan and Rob Pike) uses ctl-d.


Expanding on this, ^\ (Ctrl+\) means sigkill, and I don't think many people know about this one.


^\ is actually sigquit, which is a bit different from sigkill, since programs can catch QUIT and perform some cleanup.


Also ^| (as in, "control pipe") which is a synonym for ^\. At least for me, | is faster to hit than \

And since we're on this topic: if I write a for loop in bash that runs a slow command 1000 times (ImageMagick comes to mind), and I realise something has gone wrong, is there an easy way of breaking the outer loop?


If you wrote the for loop interactively, you can suspend it with ^Z and kill its jobspec with 'kill %n' (for n usually = 1).

If it's part of a script, your script probably wants to trap SIGINT.


> Also ^| (as in, "control pipe") which is a synonym for ^\. At least for me, | is faster to hit than \

How? Do you have a keyboard where | isn't Shift+\?


I have a Norwegian keyboard, where as you can see, pipe has its own key to the left of "1" (above Tab):

https://en.m.wikipedia.org/wiki/File:Keyboard_Layout_Norwegi...


On a Swedish keyboard, | is altgr+< (between shift and z), and \ is altgr++ (between 0 and ´).


Not a nice way, but the way that works best for me is:

^Z

fg

^C

the ^Z kills the loop, the fg and ^C cleans up the currently running one.


SIGQUIT also defaults to dumping core.


IIRC, on Unix, Ctrl-\ sends the quit signal, which causes the process receiving it to do a core dump (before exiting), which can be used for post-mortem debugging, whereas Ctrl-C sends the kill signal, which makes the process terminate without any core dump. Those are the default actions for the signals.

https://en.wikipedia.org/wiki/Control-%5C

https://en.wikipedia.org/wiki/Core_dump

https://en.wikipedia.org/wiki/Control-C

I remember doing:

sdb a.out . core

or something like that, in my C-on-Unix programming days earlier :)

sdb was a debugger.


Speaking of terminating Unix processes, here's a post I wrote a while ago:

UNIX one-liner to kill a hanging Firefox process:

http://jugad2.blogspot.in/2008/09/unix-one-liner-to-kill-han...

Some interesting comments on that post too, which go into slightly deeper details.


Wow, I can't believe I didn't know that. No more running killall in a new terminal!


So many useful (and utterly undiscoverable) tidbits of knowledge in this thread! Thanks!


This comment thread is worth much more than the actual article


Neat. So when my terminal is spewing output because I ran "cat massivefile" instead of "cat massivefile | head", I can hit ctrl-D to stop it instead of repeatedly hitting ctrl-C and despairing.


No, thats what ctrl-s and ctrl-q are for.

Here's the rest in one place:

                       eof          VEOF         EOF character
                       eol          VEOL         EOL character
                       eol2         VEOL2        EOL2 character
                       erase        VERASE       ERASE character
                       erase2       VERASE2      ERASE2 character
                       werase       VWERASE      WERASE character
                       intr         VINTR        INTR character
                       kill         VKILL        KILL character
                       quit         VQUIT        QUIT character
                       susp         VSUSP        SUSP character
                       start        VSTART       START character
                       stop         VSTOP        STOP character
                       dsusp        VDSUSP       DSUSP character
                       lnext        VLNEXT       LNEXT character
                       reprint      VREPRINT     REPRINT character
                       status       VSTATUS      STATUS character
cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>; eol2 = <undef>; erase = ^?; intr = ^C; kill = ^U; lnext = ^V; min = 1; quit = ^\; reprint = ^R; start = ^Q; status = ^T; stop = ^S; susp = ^Z; time = 0; werase = ^W;


Back in the day, using a slow modem or teletype, discard (flush output) was super important, but several years back when I hooked up an actual Wyse dumb terminal to a Linux box I was dismayed to discover that it's actually not implemented in Linux.


Nice. Reminds me of using the "stty -a" and "stty <some_param>" commands many times on Unix terminals, back in the day, for some of those settings you list, also for things like CR/LF translation (ocrnl, onlcr, ...), raw, sane, ...


I don't think so, since cat is reading from massivefile, not from your tty.


Also, a side note, I would rather just run "head massivefile" or even better "less massivefile" (because, most probably I'd want to see past what head shows by default). Running cat and then piping it to another program is inefficient, 2 forks + pipe.


But you miss out on this award if you don't use cat :p http://porkmail.org/era/unix/award.html


And on systems where head was not present (seen some earlier), but sed was, you could do:

sed nq file

where n is some positive integer, to print the first n lines of the file.

Also, body (the complement of head and tail :)

# body

sed -n $1,$2p $3


If memory serves well, there was also the amazing Ctrl-O, which allowed you to send control sequences over a busy terminal --for example when scrolling a lot of text, seems to be mapped to the arcane VDISCARD and unsupported by Posix & Linux.


huh. That's really interesting. I assume ^L is handled in the tty driver as well?


An important upshot is that TTY I/O never actually ends; EOF from a TTY is a temporary condition, and input can continue.

In the C standard library, you just clearerr(stdin) and keep reading.

If a program takes two files as input and obeys the - convention for specifying stdin (or has some other way of opening the tty more than once), you can do:

  $ program - -
then give it two inputs, each followed by [Ctrl-D][Enter]. For instance "cat - -".

This sort of thing subtly breaks with some utilities. Try coaxing GNU diff to compare two pieces of tty input, haha.


You can work around this with other shell trickery. This might work in your shell:

    $ program <(cat) <(cat)
The program itself isn't involved in opening the TTY / reading from it, etc, that is all handled by your shell before fork/execing program. program doesn't know that any of these shenanigans have happened.

It probably uses more memory (the shell has to have both stdin's in memory before it can exec the program), but overall I have mostly abandoned trying to use '-' as an input because of the way some tools, perhaps less-steeped in unix-y traditions, don't honor it correctly.


^L usually has no assigned action.

  $ stty -a | grep -F '^D'
  intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;

  $ stty -a | grep -F '^L'
  $
Your Ctrl-L clear-and-refresh command is implemented in Bash (or rather GNU readline).

There is a "reprint" action, commonly bound to ^R:

  $ stty -a | grep rprnt
  eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
It doesn't clear the screen; it just issues a newline and reprints the characters buffered so far. You can use stty to assign ^L to "rprnt".


And sadly ^t doesn't do the Tenex function of a snapshot of sysstat for the current process.


On Linux, you can compile in kernel support for a "Magic SysRq" key which causes SysRq to give you a menu of various debug printing and other actions. It works on serial consoles also, where instead of SysRq, a serial line break signal can map to the action (so it is completely out-of-band relative to serial data).

https://en.wikipedia.org/wiki/Magic_SysRq_key


It does on BSDs and OS X, but not on SYSV derivatives and Linux because NIH.


It generates SIGINFO on BSD. Which is even more useful and lets long running programs display progress of their choosing. E.g. how far has this big file copy come along?

On Linux, some programs (e.g. dd) actually do the same in SIGUSR1. I don't think it's possible to bind a key to sending USR1 so if you start a long dd you have to run the kill1 -USR from another shell. Or an awkward ^Z, then`kill -USR1 $(jobs -p)` then `fg`.


Not sure what sysstat on Tenex did, but you can still use ^T on the BSDs and Mac OS X to get the wait channel and some additional stats.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: