In Bash (as well as Bash in WSL), multiline written commands can call-back with up/down arrows correctly also built-in history command report them correctly (until I'm still logged-in in bash).
But after exiting from bash and press up/down arrows, multiline commands appears each as separate entries and that's because cat ~/.bash_history has chucked the command on multiple separate entries and writing problem here; the history command result messed too.
I have set these options in ~/.bashrc
shopt -s cmdhist lithist
HISTTIMEFORMAT='%F %T 'and now writing problem fixed but history command still report in multiple line and separate entries (reading problem now).
Bash version is 4.3, same issue on v4.4
there is this bug report since a long years but no solution yet.
Update:
it's also to mention that below multiline command as an example is correctly displaying even after exit Bash:
for i in {1..10}
do
echo $i
donebut this is failing:
awk '
{ print $1}' <<<'first last'Update 2:
the issue mentioned above is fixed in Bash v5.0.0+ that changed to recognize entries between "timestamp as delimiter" as single entry of command (HISTTIMEFORMAT, cmdhist and lithist must be set).
41 Answer
I am using GNU bash, version 5.0.3(1)-release on Ubuntu 19.10. I checked and confirmed the issue described in your question exists.
I then solved it using the following steps. After that I exited bash multiple times and confirmed the problem is solved on my system. Multi-line commands are saved to the ~/.bash_history file, retrieved and executed correctly.
#Solution:
Please edit your ~/.bashrc file or create it if it does not exist.
Copy and paste the following three lines into it and save it:
shopt -s cmdhist
shopt -s lithist
HISTTIMEFORMAT='%F %T 'From bash man-pages:
cmdhist:
If set, bash attempts to save all lines of a multiple-line command in the same history entry. This allows easy re-editing of multi-line commands.
lithist:
If set, and the cmdhist option is enabled, multi-line commands are saved to the history with embedded newlines rather than using semicolon separators where possible.
However, cmdhist and lithist are useful while the shell is still open and working from memory. When you exit the shell, the commands are saved into the ~/.bash_history file as single lines without any indication as to where a multi-line command starts or ends and then the working memory is cleared. When you run the shell again these lines in the bash history file (including the multi-line commands) will be read one line at a time and each line will be treated and loaded to working memory as a single command even though it could be a part of a multi-line command because the ~/.bash_history file will look like this:
nano .bashrc
exit
history
for i in {1..10}
do
echo $i
done
cat .bash_history
exit
history
awk '
{ print $1}' <<<'first last'
history
exitHence the need for HISTTIMEFORMAT which will act as a delimiter to separate each command from an other based on its timestamp, be it a single line or a multi-line command. So the ~/.bash_history file will look like this:
nano .bashrc
#1581635697
exit
#1581635709
history
#1581635729
for i in {1..10}
do
echo $i
done
#1581635743
cat .bash_history
#1581635757
exit
#1581635773
history
#1581635794
awk '
{ print $1}' <<<'first last'
#1581635801
history
#1581635808
exitFrom bash man-pages:
HISTTIMEFORMAT:
If this variable is set and not null, its value is used as a format string for strftime(3) to print the time stamp associated with each history entry displayed by the history builtin. If this variable is set, time stamps are written to the history file so they may be preserved across shell sessions. This uses the history comment character to distinguish timestamps from other history lines.
From now on multi-line commands will be retrieved, treated and loaded into working memory as a whole (without breaking them into single lines and treating each line as a separate command) and the history command output will look like this (even after restarting bash):
raffa@Laptop:~$ history 1 2020-02-14 05:25:19 nano .bashrc 2 2020-02-14 05:25:38 exit 3 2020-02-14 05:25:50 history 4 2020-02-14 05:27:50 for i in {1..10}
do
echo $i
done 5 2020-02-14 05:28:05 cat .bash_history 6 2020-02-14 05:28:14 exit 7 2020-02-14 05:28:27 history 8 2020-02-14 05:28:55 awk '
{ print $1}' <<<'first last' 9 2020-02-14 05:29:06 history 10 2020-02-14 05:29:16 exit 11 2020-02-14 05:29:27 historyAnd multi-line commands will be correctly retrieved, displayed and executed after exit.
Notice:
- You will need to restart your current session of bash after editing and saving the
~/.bashrcfile to activate the changes. - If your current
~/.bash_historyfile or bash working memory already contain history lines with formatting errors, you might need to delete (Please back up first) your current bash history by runninghistory -w; history -cin the terminal which will permanently delete all your current bash history.