Thursday, October 13, 2011

Traversing current command and command history

In BASH, by default emacs mode is enabled. (set -o emacs)

Traversing the Command
ctrl+f to go forward
ctrl+b to go backward
ctrl+a to go start of the line
ctrl+e to go end of the line
ctrl+p to go previous command
ctrl+n to go next command
ctrl+w to delete word backward
ctrl+k to delete from cursor to end of line
ctrl+i to search for previous commands
ctrl+d to delete letter under cursor
ctrl+l to clear the screen
ctrl+r increment search backwards, use ctrl+r to go next.

Switching between directories
"cd -" is used to switch between directories current $PWD and  $OLDPWD (where PWD is current working directory and OLDPWD is previous working directory).
cd -
for example - 
# Current directory - /home/rajashekr/Downloads
rajashekr@ubuntu:~/Downloads$ pwd
/home/rajashekr/Downloads

# Going to home directory -
rajashekr@ubuntu:~/Downloads$ cd

# To go to previous directory
rajashekr@ubuntu:~$ cd -
/home/rajashekr/Downloads

use cd- to go back to previous director

To execute previous commands
In general, you can navigate thru history by using up and down arrows
Using "!" to execute previous commands.
!<previous-command-starting-letters>
For example -
rajashekr@ubuntu:~/Downloads$ find . -name "*.txt"
./vmware-tools-distrib/doc/open_source_licenses.txt

rajashekr@ubuntu:~/Downloads$ ls
VMwareTools-8.4.7-416484.tar.gz  vmware-tools-distrib

rajashekr@ubuntu:~/Downloads$ vi test.txt

# execute previous command that start with fi
rajashekr@ubuntu:~/Downloads$ !fi
find . -name "*.txt"
./vmware-tools-distrib/doc/open_source_licenses.txt
./test.txt

Other way is to have number of the command in history
!<number-of-the-command-in-history>
$ history | grep -i find
   66  find . -name "*.java"
   67  find . -name "*.java" | grep -i paymentsummary_005fordersummary_005fwp_005ffg_jsp.java

$ !67
find . -name "*.java" | grep -i paymentsummary_005fordersummary_005fwp_005ffg_jsp.java

Tip: You can use alias.
For example: alias gh='history | grep '

$ gh find
   66  find . -name "*.java"
   67  find . -name "*.java" | grep -i paymentsummary_005fordersummary_005fwp_005ffg_jsp.java

Search previous commands with matching pattern
!?<previous-command-substring>
For example:
$ find . -name "*.txt"
./.#log.txt
./log.txt

$ find . -name "*.jsp"

$!?txt
find . -name "*.txt"
./.#log.txt
./log.txt

Use ctrl+r increment search backwards, use ctrl+r to go next.

Passing all previous arguments to current command
!*
For example -
rajashekr@ubuntu:~/Downloads$ echo test > test.txt
rajashekr@ubuntu:~/Downloads$ more test.txt
test
rajashekr@ubuntu:~/Downloads$ cat !*
cat test.txt
test

Another example :
$ touch sample.txt
$ mv !* !*.bak
mv sample.txt sample.txt.bak 

Passing only previous command last argument to current command

!$
Example:
$ echo test1 test2
test1 test2
echo !$
echo test2
test2
Substitue previous command
!!
For example:
$ find . -name "web.xml"
./actint.war/WEB-INF/web.xml
./atg_admin.war/WEB-INF/web.xml
./atg_bootstrap.war/WEB-INF/web.xml

$ grep -i atg.filter.dspjsp.PageFilter `!!`
grep -i atg.filter.dspjsp.PageFilter `find . -name "web.xml"`
./actint.war/WEB-INF/web.xml:        <filter-class>atg.filter.dspjsp.PageFilter</filter-class>
./atg_bootstrap.war/WEB-INF/web.xml:<filter-class>atg.filter.dspjsp.PageFilter</filter-class>
./common.war/WEB-INF/web.xml:        <filter-class>atg.filter.dspjsp.PageFilter</filter-class>

Substitute substring in previous command
!!:s/old/new/
or
^old^new
Example:
$echo test1
test1
$!!:s/test1/test2/
echo test2
test2
$ ^test2^test1
echo test1
test1

!!:gs/old/new/ does the same as above globally

!! is previous command
!!:0 is previous command first word
!!:1 is previous command second word

!# current command
!#:0 current command first word
mkdir test1; cd !#:1 to create directory and cd to that directory
for above !! and !# use :h for head of the word and :t for the tail of the word

To switch to vi mode
set -o vi - to have vi mode
Go through below commands to use vi keys

In ksh - Korn Shell
Make sure that you have
To enable "vi" key commands
set -o vi
To enable tab completion
set -o viraw

To navigate history
<Esc> and then use j,k to go up and down respectively
To edit current command
Use <Esc> use h,l to go previous and next letter.
Use "x" to delete current letter,
Use "r" to replace current letter.
To search previous commands
<Esc>/awk - to find previous commands which has awk in it
"n" - to go next command
"N" - to go previous command

To use "vi" to edit current buffer
<Esc>v to open current command buffer and
"wq" to execute command.
Please note that you can also set "set -o vi" in bash too and have above features.


References - mark.stosberg.com/Tech/tips/bash.tips