Using bash, how can I read the terminal answerback into a variable w/o user interaction? The following one-liner still requires Enter to be pressed once:

echo -ne '\005' && read -s && echo ${REPLY}

Also, how can I configure Xterm to send something meaningful in response to ^E? So far the only terminal emulator I've seen sending any answerback is PuTTY.


The answerback string is configurable in xterm using the answerbackString resource. That resource was added in 1998. Initially returning "xterm", since 1999 it defaults to an empty string because some users noticed the potential for abuse of control sequences which might send an unexpected command to the computer.

Other terminals may return an empty string always (konsole, mlterm, vte). But rxvt (and rxvt-unicode) return an unexpected response: the device attributes response for VT102 (an escape sequence). PuTTY returns "PuTTY" (probably due to early influence by xterm).

In a quick check, Linux console displays an "a" (probably a bug).

Because the original VT100 provided this as a setup/configurable feature, that would have been limited to printable characters. For that reason, rxvt/urxvt's response is unexpected. The manual page makes an obscure comment about this:

answerbackString: string
Specify the reply rxvt-unicode sends to the shell when an ENQ (control-E) character is passed through. It may contain escape values as described in the entry on keysym following.

(the promised description is absent).

Because the length of the answerback string is unknown, an application that reads it must allow for waiting (in case the characters arrive in more than one read operation). There is of course the ksh/bash-specific TMOUT feature which can help with shell-scripting, along with the -t option for the read command. For general use, I avoid that, using stty, e.g., (see dynamic.sh):

stty raw -echo min 0 time 5

to temporarily set the terminal so that a read will timeout in 0.5 seconds, and allow it to return without reading any characters. To see how the settings are saved/restored, it helps to read the script.

Further reading:

  • Terminal needs to be reset back to normal state once the answerback is read, via stty cooked. The complete command line would then be stty raw min 0 time 5; echo -ne '\005' && read -s; stty cooked; echo -n "${REPLY}". This produces exactly the same result as the "nibbling-on-bytes" approach suggested by thrig. – Bass Sep 29 '16 at 10:37

Even with a timeout and (some) number of characters to be read it appears bash (version 4.2.46(1)-release) may not save the REPLY, here by issuing the "Report Cursor Position" control sequence, first with a newline entered, and second waiting for the timeout:

$ echo -ne '\033[6n' && read -n 16 -s -t 3; echo -n $REPLY | xxd
0000000: 1b5b 3234 3b31 52                        .[24;1R
$ echo -ne '\033[6n' && read -n 16 -s -t 3; echo -n $REPLY | xxd

The problem here is that -n is larger than the number of bytes returned; if -n is instead exactly the right size or smaller, the response will be read without input (or a timeout) being necessary. If you know a final unique character of the response string, you can get a response by splitting "lines" by that character; for the report character position prompt that delimiter could be taken to be R:

$ echo -ne '\033[6n' && read -n 999 -d R -s; echo -n $REPLY | xxd
0000000: 1b5b 3234 3b31                           .[24;1

Given unknown input of unknown length, you'd have to either file a bug against bash, or perhaps nibble on bytes one by tedious one until the timeout triggers:

$ out="got "; echo -ne '\033[6n'; while read -n 1 -s -t 1; do out="$out$REPLY"; done
$ echo -n $out | xxd
0000000: 676f 7420 1b5b 3234 3b31 52              got .[24;1R

For the control+e thing I suppose a terminal could send something back, but would have to be configured to do so:

ENQ       Return Terminal Status (Ctrl-E).  Default response is an empty
          string, but may be overridden by a resource answerbackString.
  • I don't think this is bash only because I'm having the same problem trying to read this in python. I don't know how many bytes to read. If guess less it reads that part, but over and it hangs, even with a select timeout. – Gringo Suave Dec 14 '19 at 4:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.