Actions

Bash prompt, settings and history

From Ever changing code

.bashrc and dotfiles

There is a number of dotfiles in a user home folder that allows customizing working with terminal experience. They are:

~/.profile
executed once when you login
~/.bash_profile
scripts are executed for login shells, if exists Ubuntu won't source .bashrc
~/.bash_logout
na
~/.bash_history
the current session command history
~/.bashrc
scripts are executed for non-login interactive shells
Login shells
are run with the user logged into the system. It's still an interactive session because you input commands and the shell reads them from its standard-input. You use login shells for anything where you need user permissions or where you would like the shell to start up with consistent configuration every time.
Non-login interactive shells
do not have a user attached to its session. These are good for running automated processes that don't depend on being logged in to run.

Generic

.profile

# ~/.profile: executed by the command interpreter for login shells.

# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
# exists.  Note, however, that we will have a ~/.bash_profile and it
# will simply source this file as a matter of course.

# See /usr/share/doc/bash/examples/startup-files for examples.
# The files are located in the bash-doc package.

# From here on out, I basically set up my PATH, LD_LIBRARY_PATH, and anything else I'd like
# global to running programs and how those programs find their libraries.  This is shared by
# `cron`, so we really don't want interactive stuff, here.  Also, I setup my environments
# for brew, macports, and fink here, essentially with setting PATH, and invocation of those
# package initialization file as in:

# Brew and locally compiled stuff:
export PATH=/usr/local/bin:$PATH
export PATH=/usr/local/sbin:$PATH

# The following line puts gnu utilities without the prefix "g" in the path
# i.e. tar/gtar:
export PATH=$PATH:/usr/local/Cellar/coreutils/8.21/libexec/gnubin

# MacPorts shoves stuff in /opt, so to get at that stuff...
export PATH=/opt/local/bin:$PATH
export PATH=/opt/local/sbin:$PATH

# Set up for using Fink, which lives in /sw:
[ -e /sw/bin/init.sh ] && . /sw/bin/init.sh

# My stuff:
export PATH=~/perl:$PATH
export PATH=~/bin:$PATH
export PATH=.:$PATH


.bashrc

# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

# From here on out, I put in things that are meaningful to interactive shells, like aliases,
# `shopt` invocations, HISTORY control, terminal characteristics, PROMPT, etc.


.bash_profile

# ~/.bash_profile: executed by the command interpreter for login shells.

# Because of this file's existence, neither ~/.bash_login nor ~/.profile
# will be sourced.

# See /usr/share/doc/bash/examples/startup-files for examples.
# The files are located in the bash-doc package.

# Because ~/.profile isn't invoked if this files exists,
# we must source ~/.profile to get its settings:
if [ -r ~/.profile ]; then . ~/.profile; fi

# The following sources ~/.bashrc in the interactive login case,
# because .bashrc isn't sourced for interactive login shells:
case "$-" in *i*) if [ -r ~/.bashrc ]; then . ~/.bashrc; fi;; esac

# I'm still trying to wrap my head about what to put here.  A suggestion
# would be to put all the `bash` prompt coloring sequence functions as
# described on http://brettterpstra.com/2009/11/17/my-new-favorite-bash-prompt/

Add git branch and colour to bash prompt

This are steps to set up bash prompt showing git branch. This has been tested in Ubuntu 14lts, 16.04

Edit vi ~/.bashrc

  1. Uncomment #force_color_prompt=yes
    sed -i -E 's/^#(force_color_prompt=yes)/\1/g' ~/.bashrc
  2. Find if [ "$color_prompt" = yes ]; then statement
  3. then comment out #PS1= and add following code in bold
if [ "$color_prompt" = yes ]; then
        parse_git_branch() { git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'; }
        PS1="\u@\h \[\033[32m\]\w\[\033[33m\]\$(parse_git_branch)\[\033[00m\] $ "
       #PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ ' #default colour prompt
else
    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi

It will similar to

Git branch in bash prompt

Reload shell without logging out

. ~/.bashrc
source ~/.bashrc
exec bash
exec "$BASH"

Differences

  • source ~/.bashrc will preserve your current shell. Except for the modifications that reloading ~/.bashrc into the current shell (sourcing) makes, the current shell and its state are preserved, which includes environment variables, shell variables, shell options, shell functions, and command history.
  • exec bash, or, more robustly, exec "$BASH"[1], will replace your current shell with a new instance, and therefore only preserve your current shell's environment variables (including ones you've defined ad-hoc). In other words: Any ad-hoc changes to the current shell in terms of shell variables, shell functions, shell options, command history are lost.

[1] exec bash could in theory execute a different bash executable than the one that started the current shell, if it happens to exist in a directory listed earlier in the $PATH. Since special variable $BASH always contains the full path of the executable that started the current shell, exec "$BASH" is guaranteed to use the same executable.

Install bash auto completion

RPM based distros

Amazon Linux AMI. Version 2 has epel repo (Extra Packages for Enterprise Linux) enabled

sudo yum-config-manager --enable epel
sudo yum repolist # verify epel
sudo yum install bash-completion bash-completion-extras

Bash coloured autocomplete of symlinks

Use bash --version | grep release to find out what version of Bash you are using.

To configure it add lines below to your ~/.inputrc or system-wide /etc/inputrc

Bash 4.3 readline adds a variable that enables color for tab completion to show different colors for executable files, directories, etc., during tab completion. Readline in the upcoming Bash 4.4 adds a variable which enables colour to indicate the matching portion of the string during tab completion.

set colored-stats on             #bash 4.3
set colored-completion-prefix on #bash >=4.4

You can see the values of these variables using

bind -v | grep color

Bash autocomplete and common string with ellipses

Add to your ~/.inputrc or system-wide /etc/inputrc file

set completion-prefix-display-length 2

When you TAB to autocomplete the common string if it's longer than 2 characters will be replaced with (...) ellipses

Bash-autocomplete-common-string-into-ellipses

Bash key binding, cli shortcuts

  • CTL + a - move to BOL
  • CTL + e - move to EOL
  • ALT + f - move one word to right (forward)
  • ALT + b - move one word to left (backward)
  • CTL + u - erase line to the left/BOL
  • CTL + k - erase line to the right/EOL
  • CTL + w - erase one word to the right (forward)
  • ALT + d - erase one word to the left (backward)
  • CTL + t - switch characters places, with a character behind
  • CTL + r - reverse search of history
  • CTL + s - forward search within history
  • CTL + p/n - scroll through history up/down
  • ALT-Shift-.: Jump to the end of the history (most recent)
  • ALT-Shift-,: Jump to the beginning of the history (most distant)
  • CTL + l - clears screen

Escape sequences

  • ESC + . or !$ or !_ - is last argument of the last command

Replace last command strings

echo "first command" && echo "second command!"
!!:gs/command/echo   #call last command and substitute word "command" with "echo"
first echo
second echo!
  • Readline This is what allows for all bash key bindings, colouring etc..

Bash history

Key bindings in bash shell

  • CTL + r - reverse search of history
  • CTL + s - forward search within history
  • CTL + p/n - scroll through history up/down
  • ALT + Shift + .: Jump to the end of the history (most recent)
  • ALT + Shift + , Jump to the beginning of the history (most distant)
  • ALT + . or ESC + . -recall the last argument of any of the previous commands

Event Designators and Word designators

Event Designators
is a reference to a command line entry in the history list. Unless the reference is absolute, events are relative to the current position in the history list.
Word designators
are used to select desired words from the event. A ‘:’ separates the event specification from the word designator. It may be omitted if the word designator begins with a ‘^’, ‘$’, ‘*’, ‘-’, or ‘%’. Words are numbered from the beginning of the line, with the first word being denoted by 0 (zero). Words are inserted into the current line separated by single spaces.
  • the ! prefix is used to access previous commands.
  • !! - previous command (often pronounced "bang bang")
  • !n - command number n from history
  • !pattern - most recent command matching pattern
  • !!:s/find/replace - last command, substitute find with replace
  • $_ - last argument from previous command
  • $_ - last command's all arguments, allows call new command with previous command arguments
  • !^ and !$ - ^first and last$ argument (after the program/built-in/script) from previous command
  • !!:0 - re-call the previous command itself (just a command)
  • !!:0- hf - reproduces the previous command substituting "hf" for the last argument
  • !!:1, !!:2 recall previous command with n-number argument; examples
recall previous command with n-number argument
command with n-number argument n-command with n-argument re-call all args new command
$ touch {a,b,c}.sh
$ ls a.sh b.sh c.sh
$ ls !:2
ls a.sh
a.sh

$ ls !:2-3
ls a.sh b.sh
a.sh  b.sh
.2075  ls a.sh b.sh c.sh    #-3
 2076  cd a.sh b.sh c.sh    #-2
 2077  history              #-1
#take the first arg from the 3rd last command history
$ ls !-3:1 
ls a.sh
a.sh

 2076  cd a.sh b.sh c.sh
 2077  history 
#take 2nd arg from 2076th command history
$ ls !2076:2 
ls b.sh
b.sh
ls /tmp
cd !*
#you are now in /tmp

Delete last 10 commands from history

You can edit vi $HISTFILE file or use snippet below. It also delete the snippet execution entry.

pos=$HISTCMD; start=$(( $pos-11 )); end=$(( $pos-1 )); for i in $(eval echo "{${start}..${end}}"); do history -d $start; done

It uses $HISTCMD environment var to get the history index and uses that to delete last 10 entries in history.

References

Persistent history

To persist your history and write every command to the file add below do the end of your .bashrc

If you are Ubuntu user comment out these 2

# HISTSIZE=1000
# HISTFILESIZE=2000


Add at the end of your .bashrc

# Eternal bash history.
# ---------------------
export HISTFILESIZE=10000
export HISTSIZE=10000
export HISTTIMEFORMAT="[%F %T] "
export HISTFILE=~/.bash_eternal_history
# Force prompt to write history after every command.
PROMPT_COMMAND="history -a; $PROMPT_COMMAND"


Copy current history to new history file

$ cat ~/.bash_history >>~/.bash_eternal_history

Resources