Bash do not execute command on Ctrl+D
Matthew Martinez
Typing Ctrl+D exits bash shell as expected, but only when the command line is empty. When there's something typed on the command line, it gets executed instead as if Enter was pressed. Is there a way to make it always exit?
51 Answer
Normally the output of stty -a contains eof = ^D. This means the terminal sends EOF when you press Ctrl+d. Bash uses Readline and when there are no characters on the line and point is at the beginning of the line, Readline interprets it as the end of input, returns EOF and Bash exits.
In your case this functionality seems intact.
When the conditions are not met, a regular binding (if any) applies. Check the binding with
bind -p | grep -F '"\C-d'With the default bindings the output is "\C-d": delete-char. And this:
bind -q accept-lineusually generates
accept-line can be invoked via "\C-j", "\C-m".When I press Ctrl+v, Enter, I get ^M which means Enter is equivalent to Ctrl+m which accepts the line. This is the mechanism. I expect you to learn that in your case Ctrl+d triggers accept-line as well. This would explain the behavior in question.
Another possibility is your terminal emulator sends ^J when you press Ctrl+d and stty is set to send EOF upon ^J. This would be very unusual but it could also replicate the behavior.
Is there a way to make it always exit?
Yes. Now I assume your terminal emulator sends ^D when you press Ctrl+d and the unusual behavior you reported (executing the line) is only because of unusual binding in Readline.
In my Bash the default binding for Ctrl+u is unix-line-discard, this clears the line. I can make Ctrl+d send Ctrl+u and Ctrl+d. This will effectively work as Ctrl+d when the line is empty.
In Bash:
bind '"\C-d": "\C-u\C-d"'Or (permanent solution) in your ~/.inputrc (or /etc/inputrc):
"\C-d": "\C-u\C-d"In case you want to change your unusual binding to the default one, invoke
bind '"\C-d": delete-char'but this will affect just the shell you run it in. A permanent fix is to find where the undesired binding is defined and delete the binding. It may be
- in
~/.inputrcor/etc/inputrc(a line like"\C-d": accept-line), - or in
~/.bashrcor/etc/bash.bashrcor another file that gets sourced (a line likebind '"\C-d": accept-line').