Use Up or Down arrow keys for search
Ever since I migrated from 4DOS/NT shell on Windows to using Bash on Unix platforms I was missing its command line history access. 4NT provides for history navigation by filtering on first few letters of a command line.
This is possible on Bash too.
The key lies in activating history-search-backward and history-search-forward which by default are not binded to any keys. To verify try:
petarm@safe$ bind -p | grep history-search-forward # history-search-forward (not bound)
To activate those two commands, add this to your .bashrc file:
bind '"\e[A"':history-search-backward bind '"\e[B"':history-search-forward
Now you can easily summon any command from the history by typing the command and pressing Up arrow. You might continue pressing Up arrow until you find the command instance you wish to execute again.
Show all instances of a command
With Up or Down arrow keys you navigate commands one at a time, you are not far from the moment when you would definitely wish to see all commands that match the filter. 4NT’s way to do this is to press PgUp or PgDn key which displays a menu with all matching lines from the history. In the spirit of Bash I would do this instead (checking "cp" for example):
petarm@safe$ history | grep '^ *[0-9]* *cp' 336 cp ww_b23/src/dbghelp -R ww_b26/src 343 cp ww_b23/src/dbghelp -R ww_b27/src 348 cp dbg/ww ~/work/ww/ww_con 351 cp dbg/ww ~/work/ww/ww_g 355 cp dbg/ww ~/work/ww/ww_g_small
We can automate this as a command line macro binded to a key — Alt+W. You may wish to add this to your .bashrc file:
bind '"\M-w"':"\"\C-k\C-ahistory | grep '^ *[0-9]* *\C-e.'\C-m\""
Let me explain how this works:
-
Imagine that you have already typed the command, which is your filter. Then you press Alt+W, this expands to a macro.
-
First is Ctrl+K, which deletes everything that is on the right-hand side of the cursor, it strips down the command you already typed from any of its parameters potentially summoned by Up/Down arrow
-
It is followed by Ctrl+A, this moves the cursor at the first position of the line
-
The text of the grep command is then inserted
-
Ctrl+E moves the cursor at the end of the line, this jumps over the stripped down command, adds .
-
Ctrl+M is the equivalent of pressing Enter.
-
The dot is added for the cases when Alt+W is pressed on an empty line, then it will just show the history unfiltered.
I usually type a command, use Up or Down keys, if I can’t reach the particular one I’m looking for I quickly press Alt+W.
Picking pieces from previously executed commands
Something that is beyond 4NT, Bash has a history expansion feature — !. The problem with it is that people would usually only use simpler ! combinations and one reason I think is because there is no way to easily verify it before execution. Here comes the magic-space command. It might be unattached to any key on your system. To verify try:
petarm@safe$ bind -p | grep magic-space " ": magic-space
To attach to space bar key add this to your .bashrc file:
bind Space:magic-space
What does magic-space do: it expands any ! combinations from the command line. Look at this example history:
303 cp ww_b23/src/dbghelp -R ww_b26/src 310 cp ww_b23/src/dbghelp -R ww_b27/src 315 cp dbg/ww ~/work/ww/ww_con 318 cp dbg/ww ~/work/ww/ww_g 322 cp dbg/ww ~/work/ww/ww_g_small petarm@safe$ cp !310:1
What is "!310:1"? It means from command line 310, extract word 1, 0 based. Still it is somewhat criptic and error prone, many times you would be afraid to execute your command. Here magic-space comes to play, simply press space! Your line becomes:
petarm@safe$ cp ww_b23/src/dbghelp
You may dig and learn more about ! from Bash man pages.
Store history lines individually
4NT has an option to keep a shared memory region into which to keep the history of currently typed commands from all active instances of the shell. I couldn’t find such feature on Bash. On the other hand shared memory would keep shell instances from overwriting eachothers commands into the history file upon exit. With a combination of options Bash’s history could be configured to go to disk one line at a time, thus two instances closed at a different time would not overwrite history file contents. Add these two lines to your .bashrc:
shopt -s histappend export PROMPT_COMMAND='history -a'
First we instruct Bash not to store history by overwriting but to append lines. PROMPT_COMMAND is an environment variable which holds list of commands that will be executed before Bash begins accepting input for the next command, by calling history -a we store all commands to disk.
Back to index