Because that's what the keyboard actually sends to the PC (more precisely, what the terminal prints for what it actually receives from the keyboard). bash for example gets those values, deciphers them and understands that you want to move around, so it will either move the cursor (in case of left/right) or use its history to fetch previous commands (up/down). So you can't expect your program to magically support arrow keys.

However, reading from standard input from the terminal already supports left/right arrow keys (I believe, but I'm not in Linux right now to test and make sure). So my guess is that there is another issue interfering. One possible cause could be that one of your modifier keys is stuck? Perhaps ALT, CTRL or SUPER?

Answer from Shahbaz on Stack Overflow
🌐
Arch Linux Forums
bbs.archlinux.org › viewtopic.php
[SOLVED] A B C D printed when using arrow keys in console / Applications & Desktop Environments / Arch Linux Forums
If you have some other process running, that process decides how to interpret those key codes, which seems to be (in most cases) "just escape those characters and print them on the screen". If my thunar example does not match your problem, please give a more detailed description. ... From what you told us, I would guess that it's the expected behaviour. if I start thunar (or whatever) from a ternimal emulator, I can switch focus to the terminal emulator, hit one of the arrow keys and I get those strange characters printed.
Top answer
1 of 7
44

TLDR

You're probably running sh which outputs the raw keycodes generated when you press the Up arrow key.

A more advanced shell like bash intercepts these keycodes and does something with them. E.g. show the last command in its history.

To fix your issue, type bash to enter a bash shell. Then use the up/down arrow commands (note, your history would start afresh in the new shell).

2 of 7
32

Keyboards send events to the computer. An event says “scan code nnn down” or “scan code nnn up”. At the other end of the chain, applications running in a terminal expect input in the form of a sequence of characters. (Unless they've requested raw access, like the X server does.) When you press A, the keyboard sends the information “scan code 38 down”. The console driver looks up its keymap and transforms this into “character a” (if no modifier key is pressed).

When you press a key or key combination that doesn't result in a character, the information needs to be encoded in terms of characters. A few keys and key combinations have corresponding control characters, e.g. Ctrl+A sends the character (byte value 1), Return sends the character (Ctrl+M, byte value 13), etc. Most function keys don't have a corresponding character and instead send a sequence of characters that starts with the (escape, byte value 27) character. For example, the key Up is translated into the escape sequence ␛[A (three characters: escape, open bracket, capital A).

The user name prompt on the console is dumb and doesn't understand most escape sequences. It doesn't have the line edition and history features that you're used to: those are provided by the shell, and until you log in, you don't have a shell. So it simply displays the escape sequence. There is no glyph for the character, so it's displayed as ^[. The ^ sign is traditionally used as a prefix for control characters, and escape is ^[ because of its byte value: it's the byte value of [, minus 64.

If you press Up at a shell prompt, this sends the same 3-character sequence to your shell. The shell interprets this as a command sequence (typically to recall the previous history item). If you press Ctrl+V then Up at a shell prompt, this inserts the escape sequence at the prompt: Ctrl+V is a command to insert the next character literally instead of interpreting it as a command, so the character is not interpreted as the start of an escape sequence.

Some keys are only modifiers and are not transmitted to terminal applications. For example, when you press Shift, this information stays in the terminal driver, and is taken into account if you then press A, so the driver sends A to the application instead of a.

Additionally some function keys may not be mapped in your console.

For a similar view in the GUI, see What is bash's meta key?

🌐
Medium
teresa11000.medium.com › kali-linux-terminal-gets-abcd-while-pressing-arrow-keys-instead-of-fetching-previous-commands-of-ffe810b5b99
Kali Linux terminal gets ABCD while pressing Arrow keys instead of fetching previous commands of the terminal. | by Teresa | Medium
September 7, 2023 - But if pressing the arrow keys gives output like A for up-arrow, B for down arrow, C for right-arrow and D for left arrow key that clearly states that there is issue with selecting the emulator in the terminal.
Find elsewhere
🌐
CopyProgramming
copyprogramming.com › howto › why-does-the-terminal-show-a-b-c-d-when-pressing-the-arrow-keys-in-ubuntu
Ubuntu: What is the reason for ^[[A ^[[B ^[[C ^[[D appearing on Ubuntu terminal upon pressing arrow keys?
May 11, 2023 - When the "Lt" key is pressed, it produces the output " ^[[D ". ... The keyboard sends certain values to the PC, which are then printed by the terminal. For instance, bash is deciphered by the system to understand that you wish to move around. It can either move the cursor (for left/right) or retrieve previous commands (for up/down) from its history. Therefore, it is unrealistic to anticipate your program to automatically support arrow keys.
🌐
Linode
linode.com › community › questions › 23026 › why-is-my-terminal-typing-weird-characters
Why is my Terminal typing weird characters? (23026) | Linode Questions
This is a "bash" problem: that you can't use your keys like Ctrl-L to clear the screen, up-arrow for history, etc. Searched high and low for the solution, and finally, after much debugging, Perplexity.ai showed me the solution: This is because you are not using bash as the default shell...
Top answer
1 of 2
20

This is a keyboard input protocol that goes back to the 1980s, and your shell, not your "terminal driver" (whatever that is supposed to be) as in M. Vazquez-Abrams's answer, is not handling it properly. It is, moreover, a perfectly valid control sequence.

Background

Terminals emit control sequences for function key and extended key presses. They can emit DECFNK control sequences, which are CSI-introduced control sequences; Linux function key control sequences, which are a different kind of CSI-introduced sequence; SCO console function key control sequences, which are a third kind of CSI-introduced sequence; shifted single characters, prefixed with SS3; or, as in this case, ECMA-48 standard sequences for various things.

(SS3 and CSI are control characters, in the C1 range. Single Shift 3 and Control Sequence Introducer.)

You have two particular keypads on your (IBM Model M-alike or similar) keyboard, a calculator keypad and a cursor keypad. The model employed by DEC VT-style terminal emulators (which is most of the terminal emulators that you are likely to encounter, from the one in your kernel to unicode-rxvt) is that both keypads have separately switchable application/normal modes. A full-screen TUI application, something using the libedit or GNU readline libraries (or ZLE) such as your shell, and a few other types of application specify which mode they want, and then listen for control sequences coming from the terminal by reading bursts of characters (on the grounds that a human cannot type a full ECMA-48 control sequence anywhere near as fast as a terminal or a terminal emulator sends control sequences, so all coming in one burst is what distinguishes a user pressing the Esc key from the terminal emulator sending a control sequence starting with the ␛ character).

  • In application mode, the arrow keys on each keypad produce shifted single characters prefixed with SS3. Modifiers cannot really have any effect (despite XTerm having botched this) because ECMA-35 and ECMA-48 define SS2 and SS3 as only acting on a single following character. But, on the flip side, the calculator and cursor keypads generate different SS3-shifted characters, allowing the two keypads to be distinguished from each other.
  • In normal mode, the arrow keys on each keypad produce the same CSI-introduced control sequences, and they are the ones from ECMA-48 with augmentations from DEC VTs. In particular, the cursor keys send the ECMA-48 control sequences CUU, CUD, CUR, and CUL (CUrsor Up, CUrsor Down, CUrsor Right, and CUrsor Left). The DEC augmentations to the ECMA-48 control sequences are that the control sequence includes the current modifier state.

So one has a choice between application mode, where one cannot know what modifiers are pressed but one can distinguish the two Left Arrow keys, and normal mode, where one cannot distinguish between two arrow keys but one can know what modifiers are pressed.

In more detail: The DEC augmentations to the ECMA-48 control sequences are that the control sequence has two parameters:

  • The first parameter is analogous to the first parameter than a CUU, CUD, CUR, or CUL can actually have, per ECMA-48. It is the occurrence count, and is thus always 1.
  • The second parameter is the interesting one. It contains the modifier key state, which (for reasons involving how parameters in CSI-introduced control sequences work when omitted) is a set of bitflags for various modifier keys, plus 1, encoded as a decimal number.

This is how DEC VT terminals have been doing things since the 1980s. In recent years, several terminal emulators finally introduced the same functionality (albeit, as mentioned, XTerm got it rather wrong).

What's going on.

The problem is that your GNU readline library, libedit, ZLE, and so forth don't really handle the protocol properly. They are not totally to blame. They rely upon the termcap and terminfo systems, which simply aren't up to the job here. termcap and terminfo don't really have the notion of an input control sequence that can vary, let alone multiple-mode keypads.

For that you have to look to the likes of Vim, which can be programmed with special overrides for terminfo to specify control sequences that follow the aforegiven protocol (c.f. :help xterm-modifier-keys in Vim), or NeoVIM, which uses Paul Evans's libtermkey and its CSI driver. libtermkey's CSI driver is how one has to handle keyboard input properly from DEC VT-alike terminal emulators. It's an actual ECMA-48 state machine parser that decodes control sequences properly.

But what your shell is doing is looking up entries for the arrow keys in terminfo, and only matching those specific control sequences.

Specifically:

  • Your shell is looking up the kcub1 capability for your terminal in its terminfo record. Here's the one from the teken record, for example:
    % tput -T teken kcub1|hexdump -C
    00000000  1b 5b 44                                          |.[D|
    00000003
    %
  • It is only matching that specific input sequence as ← Left Arrow.
  • When you press ⇧ Level 2 Shift+← Left Arrow your terminal emulator is sending the control sequence CSI 1 ; 2 D. Rather, it is using the 7-bit alternatives and sending [ 1 ; 2 D, where [ is the way of encoding CSI in 7-bit characters.
  • Your shell fails to match that against any known fixed input sequence from terminfo, and aborts processing. On my Bourne Again shell here, it ends up swallowing the first two characters and acts as if I have pressed ; 2 D. On your Bourne Again shell, it ends up swallowing the first four characters and acts as if you have pressed D.

    What the failure mode is is dependent from exactly what set of input sequences it is attempting to pattern match, as that determines how many characters it swallows before it determines that it has a sequence with no possible matches. This of course is in turn dependent from what your terminal's terminfo/termcap record actually contains and what terminal type you have told your shell that your terminal is.

Fixes

The local fix for this sort of thing is to get creative with the keybindings in your shell. It's why, for example, you'll find people doing this sort of thing with the Z shell in their .zshrcs:

bindkey "\e[1;5D" backward-word
bindkey "\e[1;5C" forward-word

The previously mentioned "fix" moves the cursor back one word, it does NOT allow selecting text using Shift + Arrow keys.

Unfortunately, there is no non-local fix. It would involve rearchitecting your shell's input handling quite significantly. Such rearchitecting is long overdue. (Witness NeoVIM.) But no-one has tackled it yet.

Further reading

  • Character Code Structure and Extension Techniques . ECMA-35. 6th edition. 1994. ECMA International.
  • Control Functions for Coded Character Sets. ECMA-48. 5th edition. 1991. ECMA International.
  • "ANSI, Short ANSI, and PC Keyboard Codes". VT420 Programmer Reference Manual. EK-VT420-RM-002. February 1992. Digital.
  • DECFNK. "ANSI Control Functions". VT510 Terminal Programmer Information. EK-VT510-RM. November 1993. Digital.
  • VT520/VT525 Video Terminal Programmer Information. EK-VT520-RM. July 1994. Digital.
  • https://github.com/fish-shell/fish-shell/issues/2139#issuecomment-388706768
  • https://unix.stackexchange.com/a/238932/5132
2 of 2
3

Pressing Ctrl+V will cause the next keypress to be input literally. For Shift+ this results in "^[[1;2A". The terminal driver consumes the "^[[1;2" as an invalid escape sequence, leaving only the "A".

🌐
Linux Mint Forums
forums.linuxmint.com › board index › main edition support › software & applications
Terminal arrow keys not working, please help - Linux Mint Forums
I appear to be running sh which is a link to dash. I think this may have happened when I installed the game Billiard-GL which I can't uninstall. My .bash_history hasn't updated since then. I could really use some help getting my computer back to where it was and I think the first step would be to get bash back.
🌐
GitHub
github.com › microsoft › terminal › issues › 3101
Alt arrow keys print extra characters · Issue #3101 · microsoft/terminal
October 7, 2019 - Terminal App ubuntu: A◘B☻C♠D♦ is printed out. Terminal App ubuntu in byobu: Byobu tabs are are switched as expected, BUT when alt is released one of ◘☻♠♦ is printed out depending on which arrow key was pressed last.
Published   Oct 07, 2019
🌐
Fandom
vim.fandom.com › wiki › Fix_arrow_keys_that_display_A_B_C_D_on_remote_shell
Fix arrow keys that display A B C D on remote shell | Vim Tips Wiki | Fandom
I had the arrow keys switching from normal mode to insert mode when I was using vim in the terminal: E.g. pressing "up" would do the same as <Esc>OA, where <Esc> had no effect, O would switch to insert mode, and A would enter the letter "A". The reason was that I in my .vimrc I had mapped <Esc> in normal mode to do funky stuff. Removing the mapping fixed it. On my default Ubuntu install, vi meant actual vi, but I was used to vim where this problem didn't occur.
🌐
Adoclib
adoclib.com › blog › why-does-the-terminal-show-a-b-c-d-when-pressing-the-arrow-keys-in-ubuntu.html
Why Does The Terminal Show "^[[A" "^[[B" "^[[C" "^[[D" When Pressing The Arrow Keys In Ubuntu
It's more likely that the problem is that Vim doesn't recognise the escape The correct way to fix this would be to fix your terminal configuration so that your reports the sequences that are actually sent when you press the arrow keys but the map is being set which is particularly useful if ...