How can I make the builtin read command support history, by pressing the up/down key to cycle through them?

I've tried catching when you press the up key, however it doesn't seem to work with read:

read -p '> ' -n 3 foo
echo -n "$foo" | hexdump

Pressing the arrow keys seems to work and I can detect it using this, however if I press aa, it will fail as it will only read the first character of the identifier of the up-arrow, while the third is needed to distinguish the different arrow keys.


2 Answers 2


To copy Mike Stroyan's great answer from this old mailing list post:

You can use "history -r" to read a file into the shell's history and "history -s" to add each line that you read into the history. Then use history -w to save the history back to the file. Here is an example with vi style readline editing.

history -r script_history
set -o vi
while true
    echo "Type something"
    read -e CMD
    history -s "$CMD"
    echo "You typed $CMD"
    case "$CMD" in
history -w script_history
echo stopping
  • 1
    I like this solution better than rlwrap as (at least on my machine) rlwrap is unable to handle CTRL-C gracefully, e.g. try running USERINPUT=$(rlwrap -o cat) and pressing CTRL-C and see how your terminal behaves afterwards (run the reset command to return to a sane state again).
    – zpon
    Jan 4, 2017 at 7:40
  • 1
    This works really nicely if you don't want to install additional libs and you are happy using a separate file to manage input.
    – Luke Exton
    Mar 21, 2017 at 16:39

You can use rlwrap for this, if you don't mind installing software.

You'll probably want to keep a separate history file that only maintains history for the particular prompt in your script (ie. avoid mixing with the user's shell command history).

Here's an example that might work for you:

# Save in rlwrap_example.sh

USERINPUT=$(rlwrap -H $HISTORY sh -c 'read REPLY && echo $REPLY')
echo "User said $USERINPUT"

$ ./rlwrap_example.sh
User said hello

In the above script, the user can use all GNU readline functionality, with history served from — and stored in — ~/.myscript_history. Tweak as needed.

Alternatively, you can use bash's read -e, which enables readline for read invocations, but you will probably find its history functionality too limited (ie. almost nonexistent).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .