Как создать свою Unix подсказку более полезной и интересной

от автора

Хватит “#” и “$”? Вы можете сделать свой bash подсказок более интересной и полезной в дальнейшей настройки. Вы можете даже изменять цвет шрифта или изменить Вашу подсказку в зависимости от того где Вы находитесь в файловой системе, в какой системы Вы работаете и сколько времени.

Специализированные подсказки могут помогать, как намек, что система работает, особенно полезно если Вы часто находите себя зарегистрированными в 3-4 системы одновременно, переходя по окнам, чтоб получить некоторые вещие, сделанных в одно и тоже время или если Вы авторизировались с разных аккаунтов. Настроенная подсказка может помочь, если Вам нравится напоминание, когда Вы находитесь в файловой системе или предпочитаете не получать напоминание.

Все что Вы должны сделать, чтоб определить свой переменный PS1 и сохранить их у Вашей

.bashrc

Приложение G. Пример файла .bashrc

Файл ~/.bashrc определяет поведение командной оболочки. Внимательное изучение этого примера поможет вам значительно продвинуться в понимании Bash.

Emmanuel Rouat представил следующий, очень сложный, файл .bashrc, написанный для операционной системы Linux. Предложения и замечания приветствуются.

Внимательно изучите этот файл. Отдельные участки этого файла вы свободно можете использовать в своем собственном .bashrc или, даже в своих сценариях!

Пример G-1. Пример файла .bashrc

#===============================================================
#
# ЛИЧНЫЙ ФАЙЛ $HOME/.bashrc для bash-2.05a (или выше)
#
# Время последней модификации: Втр Апр 15 20:32:34 CEST 2003
#
# Этот файл содержит настройки интерактивной командной оболочки.
# Здесь размещены определения псевдонимов, функций
# и других элементов Bash, таких как prompt (приглашение к вводу).
#
# Изначально, этот файл был создан в операционной системе Solaris,
# но позднее был переделан под Redhat
# —> Модифицирован под Linux.
# Большая часть кода, который находится здесь, была взята из
# Usenet (или Интернет).
# Этот файл содержит слишком много определений — помните, это всего лишь пример.
#
#
#===============================================================

# —> Комментарии, добавленные автором HOWTO.
# —> И дополнены автором сценария Emmanuel Rouat 🙂

#————————————
# Глобальные определения
#————————————

if [ -f /etc/bashrc ]; then
. /etc/bashrc # —> Прочитать настройки из /etc/bashrc, если таковой имеется.
fi

#————————————————————-
# Настройка переменной $DISPLAY (если еще не установлена)
# Это срабатывает под linux — в вашем случае все может быть по другому…
# Проблема в том, что различные типы терминалов
# дают разные ответы на запрос ‘who am i’…
# я не нашел ‘универсального’ метода
#————————————————————-

function get_xserver ()
{
case $TERM in
xterm )
XSERVER=$(who am i | awk ‘{print $NF}’ | tr -d ‘)»(‘ )
XSERVER=${XSERVER%%:*}
;;
aterm | rxvt)
# добавьте здесь свой код…
;;
esac
}

if [ -z ${DISPLAY:=""} ]; then
get_xserver
if [[ -z ${XSERVER} || ${XSERVER} == $(hostname) || ${XSERVER} == «unix» ]]; then
DISPLAY=":0.0" # для локального хоста
else
DISPLAY=${XSERVER}:0.0 # для удаленного хоста
fi
fi

export DISPLAY

#—————
# Некоторые настройки
#—————

ulimit -S -c 0 # Запрет на создание файлов coredump
set -o notify
set -o noclobber
set -o ignoreeof
set -o nounset
#set -o xtrace # полезно для отладки

# Разрешающие настройки:
shopt -s cdspell
shopt -s cdable_vars
shopt -s checkhash
shopt -s checkwinsize
shopt -s mailwarn
shopt -s sourcepath
shopt -s no_empty_cmd_completion # только для bash>=2.04
shopt -s cmdhist
shopt -s histappend histreedit histverify
shopt -s extglob

# Запрещающие настройки:
shopt -u mailwarn
unset MAILCHECK # Я не желаю, чтобы командная оболочка сообщала мне о прибытии почты

export TIMEFORMAT=$’\nreal %3R\tuser %3U\tsys %3S\tpcpu %P\n’
export HISTIGNORE="&:bg:fg:ll:h"
export HOSTFILE=$HOME/.hosts # Поместить список удаленных хостов в файл ~/.hosts

#————————
# Greeting, motd etc…
#————————

# Для начала определить некоторые цвета:
red=’\e[0;31m’
RED=’\e[1;31m’
blue=’\e[0;34m’
BLUE=’\e[1;34m’
cyan=’\e[0;36m’
CYAN=’\e[1;36m’
NC=’\e[0m’ # No Color (нет цвета)
# —> Прекрасно. Имеет тот же эффект, что и «ansi.sys» в DOS.

# Лучше выглядит на черном фоне…
echo -e "${CYAN}This is BASH ${RED}${BASH_VERSION%.*}${CYAN} — DISPLAY on ${RED}$DISPLAY${NC}\n"
date
if [ -x /usr/games/fortune ]; then
/usr/games/fortune -s # сделает наш день более интересным… 🙂
fi

function _exit() # функция, запускающаяся при выходе из оболочки
{
echo -e "${RED}Аста ла виста, бэби ${NC}"
}
trap _exit EXIT

#—————
# Prompt
#—————

if [[ "${DISPLAY#$HOST}" != ":0.0" && "${DISPLAY}" != ":0" ]]; then
HILIT=${red} # на удаленной системе: prompt будет частично красным
else
HILIT=${cyan} # на локальной системе: prompt будет частично циановым
fi

# —> Замените \W на \w в функциях ниже
#+ —> чтобы видеть в оболочке полный путь к текущему каталогу.

function fastprompt()
{
unset PROMPT_COMMAND
case $TERM in
*term | rxvt )
PS1="${HILIT}[\h]$NC \W > \[\033]0;\${TERM} [\u@\h] \w\007\]" ;;
linux )
PS1="${HILIT}[\h]$NC \W > " ;;
*)
PS1="[\h] \W > " ;;
esac
}

function powerprompt()
{
_powerprompt()
{
LOAD=$(uptime|sed -e «s/.*: \([^,]*\).*/\1/» -e «s/ //g»)
}

PROMPT_COMMAND=_powerprompt
case $TERM in
*term | rxvt )
PS1="${HILIT}[\A \$LOAD]$NC\n[\h \#] \W > \[\033]0;\${TERM} [\u@\h] \w\007\]" ;;
linux )
PS1="${HILIT}[\A — \$LOAD]$NC\n[\h \#] \w > " ;;
* )
PS1="[\A — \$LOAD]\n[\h \#] \w > " ;;
esac
}

powerprompt # это prompt по-умолчанию — может работать довольно медленно
# Если это так, то используйте fastprompt…

#===============================================================
#
# ПСЕВДОНИМЫ И ФУНКЦИИ
#
# Возможно некоторые из функций, приведенных здесь, окажутся для вас слишком большими,
# но на моей рабочей станции установлено 512Mb ОЗУ, так что…
# Если пожелаете уменьшить размер этого файла, то можете оформить эти функции
# в виде отдельных сценариев.
#
# Большинство функций были взяты, почти без переделки, из примеров
# к bash-2.04.
#
#===============================================================

#——————-
# Псевдонимы
#——————-

alias rm=’rm -i’
alias cp=’cp -i’
alias mv=’mv -i’
# -> Предотвращает случайное удаление файлов.
alias mkdir=’mkdir -p’

alias h=’history’
alias j=’jobs -l’
alias r=’rlogin’
alias which=’type -all’
alias ..=’cd ..’
alias path=’echo -e ${PATH//:/\\n}’
alias print=’/usr/bin/lp -o nobanner -d $LPDEST’ # Предполагается, что LPDEST определен
alias pjet=’enscript -h -G -fCourier9 -d $LPDEST’ # Печать через enscript
alias background=’xv -root -quit -max -rmode 5′ # Положить картинку в качестве фона
alias du=’du -kh’
alias df=’df -kTh’

# Различные варианты ‘ls’ (предполагается, что установлена GNU-версия ls)
alias la=’ls -Al’ # показать скрытые файлы
alias ls=’ls -hF —color’ # выделить различные типы файлов цветом
alias lx=’ls -lXB’ # сортировка по расширению
alias lk=’ls -lSr’ # сортировка по размеру
alias lc=’ls -lcr’ # сортировка по времени изменения
alias lu=’ls -lur’ # сортировка по времени последнего обращения
alias lr=’ls -lR’ # рекурсивный обход подкаталогов
alias lt=’ls -ltr’ # сортировка по дате
alias lm=’ls -al |more’ # вывод через ‘more’
alias tree=’tree -Csu’ # альтернатива ‘ls’

# подготовка ‘less’
alias more=’less’
export PAGER=less
export LESSCHARSET=’latin1′
export LESSOPEN=’|/usr/bin/lesspipe.sh %s 2>&-‘ # если существует lesspipe.sh
export LESS=’-i -N -w -z-4 -g -e -M -X -F -R -P%t?f%f \
:stdin .?pb%pb\%:?lbLine %lb:?bbByte %bb:-…’

# проверка правописания — настоятельно рекомендую 🙂
alias xs=’cd’
alias vf=’cd’
alias moer=’more’
alias moew=’more’
alias kk=’ll’

#—————-
# добавим немножко «приятностей»
#—————-

function xtitle ()
{
case "$TERM" in
*term | rxvt)
echo -n -e "\033]0;$*\007" ;;
*)
;;
esac
}

# псевдонимы…
alias top=’xtitle Processes on $HOST && top’
alias make=’xtitle Making $(basename $PWD); make’
alias ncftp=«xtitle ncFTP; ncftp»

#… и функции
function man ()
{
for i; do
xtitle The $(basename $1|tr -d .[:digit:]) manual
command man -F -a "$i"
done
}

function ll(){ ls -l "$@"| egrep "^d"; ls -lXB "$@" 2>&-| egrep -v "^d|total "; }
function te() # «обертка» вокруг xemacs/gnuserv
{
if [ "$(gnuclient -batch -eval t 2>&-)" == «t» ]; then
gnuclient -q "$@";
else
( xemacs "$@" &);
fi
}

#————————————
# Функции для работы с файлами и строками:
#————————————

# Поиск файла по шаблону:
function ff() { find. -type f -iname ‘*’$*’*’ -ls; }
# Поиск файла по шаблону в $1 и запуск команды в $2 с ним:
function fe() { find. -type f -iname ‘*’$1’*’ -exec "${2:-file}" {} \;; }
# поиск строки по файлам:
function fstr()
{
OPTIND=1
local case=""
local usage=«fstr: поиск строки в файлах.
Порядок использования: fstr [-i] \»шаблон\" [\«шаблон_имени_файла\»] "
while getopts :it opt
do
case "$opt" in
i) case="-i " ;;
*) echo "$usage"; return;;
esac
done
shift $(( $OPTIND — 1 ))
if [ "$#" -lt 1 ]; then
echo "$usage"
return;
fi
local SMSO=$(tput smso)
local RMSO=$(tput rmso)
find. -type f -name "${2:-*}" -print0 | xargs -0 grep -sn ${case} "$1" 2>&- | \
sed «s/$1/${SMSO}\0${RMSO}/gI» | more
}

function cuttail() # удалить последние n строк в файле, по-умолчанию 10
{
nlines=${2:-10}
sed -n -e :a -e «1,${nlines}!{P;N;D;};N;ba» $1
}

function lowercase() # перевести имя файла в нижний регистр
{
for file; do
filename=${file##*/}
case "$filename" in
*/*) dirname==${file%/*} ;;
*) dirname=.;;
esac
nf=$(echo $filename | tr A-Z a-z)
newname="${dirname}/${nf}"
if [ "$nf" != "$filename" ]; then
mv "$file" "$newname"
echo «lowercase: $file —> $newname»
else
echo «lowercase: имя файла $file не было изменено.»
fi
done
}

function swap() # меняет 2 файла местами
{
local TMPFILE=tmp.$$
mv "$1" $TMPFILE
mv "$2" "$1"
mv $TMPFILE "$2"
}

#————————————
# Функции для работы с процессами/системой:
#————————————

function my_ps() { ps $@ -u $USER -o pid,%cpu,%mem,bsdtime,command; }
function pp() { my_ps f | awk ‘!/awk/ && $0~var’ var=${1:-".*"}; }

# Эта функция является грубым аналогом ‘killall’ в linux
# но не эквивалентна (насколько я знаю) ‘killall’ в Solaris
function killps() # «Прибить» процесс по его имени
{
local pid pname sig="-TERM" # сигнал, рассылаемый по-умолчанию
if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then
echo «Порядок использования: killps [-SIGNAL] шаблон_имени_процесса»
return;
fi
if [ $# = 2 ]; then sig=$1; fi
for pid in $(my_ps| awk ‘!/awk/ && $0~pat { print $1 }’ pat=${!#} ); do
pname=$(my_ps | awk ‘$1~var { print $5 }’ var=$pid )
if ask «Послать сигнал $sig процессу $pid <$pname>?»
then kill $sig $pid
fi
done
}

function my_ip() # IP адрес
{
MY_IP=$(/sbin/ifconfig ppp0 | awk ‘/inet/ { print $2 } ‘ | sed -e s/addr://)
MY_ISP=$(/sbin/ifconfig ppp0 | awk ‘/P-t-P/ { print $3 } ‘ | sed -e s/P-t-P://)
}

function ii() # Дополнительные сведения о системе
{
echo -e "\nВы находитесь на ${RED}$HOST"
echo -e "\nДополнительная информация:$NC "; uname -a
echo -e "\n${RED}В системе работают пользователи:$NC "; w -h
echo -e "\n${RED}Дата:$NC "; date
echo -e "\n${RED}Время, прошедшее с момента последней перезагрузки :$NC "; uptime
echo -e "\n${RED}Память :$NC "; free
my_ip 2>&-;
echo -e "\n${RED}IP адрес:$NC"; echo ${MY_IP:-«Соединение не установлено»}
echo -e "\n${RED}Адрес провайдера (ISP):$NC"; echo ${MY_ISP:-«Соединение не установлено»}
echo
}

# Разные утилиты:

function repeat() # повторить команду n раз
{
local i max
max=$1; shift;
for ((i=1; i <= max; i++)); do # —> C-подобный синтаксис
eval "$@";
done
}

function ask()
{
echo -n "$@" ‘[y/n] ‘; read ans
case "$ans" in
y*|Y*) return 0 ;;
*) return 1 ;;
esac
}

#=========================================================================
#
# ПРОГРАММНЫЕ ДОПОЛНЕНИЯ — ТОЛЬКО НАЧИНАЯ С ВЕРСИИ BASH-2.04
# Большая часть дополнений взята из докуентации к bash 2.05 и из
# пакета ‘Bash completion’ (http://www.caliban.org/bash/index.shtml#completion)
# автор — Ian McDonalds
# Фактически, у вас должен стоять bash-2.05a
#
#=========================================================================

if [ "${BASH_VERSION%.*}" \< «2.05» ]; then
echo «Вам необходимо обновиться до версии 2.05»
return
fi

shopt -s extglob # необходимо
set +o nounset # иначе некоторые дополнения не будут работать

complete -A hostname rsh rcp telnet rlogin r ftp ping disk
complete -A export printenv
complete -A variable export local readonly unset
complete -A enabled builtin
complete -A alias alias unalias
complete -A function function
complete -A user su mail finger

complete -A helptopic help
complete -A shopt shopt
complete -A stopped -P ‘%’ bg
complete -A job -P ‘%’ fg jobs disown

complete -A directory mkdir rmdir
complete -A directory -o default cd

# Архивация
complete -f -o default -X ‘*.+(zip|ZIP)’ zip
complete -f -o default -X ‘!*.+(zip|ZIP)’ unzip
complete -f -o default -X ‘*.+(z|Z)’ compress
complete -f -o default -X ‘!*.+(z|Z)’ uncompress
complete -f -o default -X ‘*.+(gz|GZ)’ gzip
complete -f -o default -X ‘!*.+(gz|GZ)’ gunzip
complete -f -o default -X ‘*.+(bz2|BZ2)’ bzip2
complete -f -o default -X ‘!*.+(bz2|BZ2)’ bunzip2
# Postscript,pdf,dvi…
complete -f -o default -X ‘!*.ps’ gs ghostview ps2pdf ps2ascii
complete -f -o default -X ‘!*.dvi’ dvips dvipdf xdvi dviselect dvitype
complete -f -o default -X ‘!*.pdf’ acroread pdf2ps
complete -f -o default -X ‘!*.+(pdf|ps)’ gv
complete -f -o default -X ‘!*.texi*’ makeinfo texi2dvi texi2html texi2pdf
complete -f -o default -X ‘!*.tex’ tex latex slitex
complete -f -o default -X ‘!*.lyx’ lyx
complete -f -o default -X ‘!*.+(htm*|HTM*)’ lynx html2ps
# Multimedia
complete -f -o default -X ‘!*.+(jp*g|gif|xpm|png|bmp)’ xv gimp
complete -f -o default -X ‘!*.+(mp3|MP3)’ mpg123 mpg321
complete -f -o default -X ‘!*.+(ogg|OGG)’ ogg123

complete -f -o default -X ‘!*.pl’ perl perl5

# Эти ‘универсальные’ дополнения работают тогда, когда команды вызываются
# с, так называемыми, ‘длинными ключами’, например: ‘ls —all’ вместо ‘ls -a’

_get_longopts ()
{
$1 —help | sed -e ‘/—/!d’ -e ‘s/.*—\([^[:space:].,]*\).*/—\1/’| \
grep ^"$2" |sort -u;
}

_longopts_func ()
{
case "${2:-*}" in
-*) ;;
*) return ;;
esac

case "$1" in
\~*) eval cmd="$1" ;;
*) cmd="$1" ;;
esac
COMPREPLY=( $(_get_longopts ${1} ${2} ) )
}
complete -o default -F _longopts_func configure bash
complete -o default -F _longopts_func wget id info a2ps ls recode

_make_targets ()
{
local mdef makef gcmd cur prev i

COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
prev=${COMP_WORDS[COMP_CWORD-1]}

# Если аргумент prev это -f, то вернуть возможные варианты имен файлов.
# будем великодушны и вернем несколько вариантов
# `makefile Makefile *.mk’
case "$prev" in
-*f) COMPREPLY=( $(compgen -f $cur ) ); return 0;;
esac

# Если запрошены возможные ключи, то вернуть ключи posix
case "$cur" in
-) COMPREPLY=(-e -f -i -k -n -p -q -r -S -s -t); return 0;;
esac

# попробовать передать make `makefile’ перед тем как попробовать передать `Makefile’
if [ -f makefile ]; then
mdef=makefile
elif [ -f Makefile ]; then
mdef=Makefile
else
mdef=*.mk
fi

# прежде чем просмотреть «цели», убедиться, что имя makefile было задано
# ключом -f
for (( i=0; i < ${#COMP_WORDS[@]}; i++ )); do
if [[ ${COMP_WORDS[i]} == -*f ]]; then
eval makef=${COMP_WORDS[i+1]}
break
fi
done

[ -z "$makef" ] && makef=$mdef

# Если задан шаблон поиска, то ограничиться
# этим шаблоном
if [ -n "$2" ]; then gcmd=’grep "^$2"’; else gcmd=cat; fi

# если мы не желаем использовать *.mk, то необходимо убрать cat и использовать
# test -f $makef с перенаправлением ввода
COMPREPLY=( $(cat $makef 2>/dev/null | awk ‘BEGIN {FS=":"} /^[^.# ][^=]*:/ {print $1}’ | tr -s ‘ ‘ ‘\012’ | sort -u | eval $gcmd ) )
}

complete -F _make_targets -X ‘+($*|*.[cho])’ make gmake pmake

# cvs(1) completion
_cvs ()
{
local cur prev
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
prev=${COMP_WORDS[COMP_CWORD-1]}

if [ $COMP_CWORD -eq 1 ] || [ "${prev:0:1}" = "-" ]; then
COMPREPLY=( $( compgen -W ‘add admin checkout commit diff \
export history import log rdiff release remove rtag status \
tag update’ $cur ))
else
COMPREPLY=( $( compgen -f $cur ))
fi
return 0
}
complete -F _cvs cvs

_killall ()
{
local cur prev
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}

# получить список процессов
COMPREPLY=( $( /usr/bin/ps -u $USER -o comm | \
sed -e ‘1,1d’ -e ‘s#[]\[]##g’ -e ‘s#^.*/##’| \
awk ‘{if ($0 ~ /^’$cur’/) print $0}’ ))

return 0
}

complete -F _killall killall killps

# Функция обработки мета-команд
# В настоящее время недостаточно отказоустойчива (например, mount и umount
# обрабатываются некорректно), но все еще актуальна. Автор Ian McDonald, изменена мной.

_my_command()
{
local cur func cline cspec

COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}

if [ $COMP_CWORD = 1 ]; then
COMPREPLY=( $( compgen -c $cur ) )
elif complete -p ${COMP_WORDS[1]} &>/dev/null; then
cspec=$( complete -p ${COMP_WORDS[1]} )
if [ "${cspec%%-F *}" != "${cspec}" ]; then
# complete -F <function>
#
# COMP_CWORD and COMP_WORDS() доступны на запись,
# так что мы можем установить их перед тем,
# как передать их дальше

# уменьшить на 1 текущий номер лексемы
COMP_CWORD=$(( $COMP_CWORD — 1 ))
# получить имя функции
func=${cspec#*-F }
func=${func%% *}
# получить командную строку, исключив первую команду
cline="${COMP_LINE#$1 }"
# разбить на лексемы и поместить в массив
COMP_WORDS=( $cline )
$func $cline
elif [ "${cspec#*-[abcdefgjkvu]}" != "" ]; then
# complete -[abcdefgjkvu]
#func=$( echo $cspec | sed -e ‘s/^.*\(-[abcdefgjkvu]\).*$/\1/’ )
func=$( echo $cspec | sed -e ‘s/^complete//’ -e ‘s/[^ ]*$//’ )
COMPREPLY=( $( eval compgen $func $cur ) )
elif [ "${cspec#*-A}" != "$cspec" ]; then
# complete -A <type>
func=${cspec#*-A }
func=${func%% *}
COMPREPLY=( $( compgen -A $func $cur ) )
fi
else
COMPREPLY=( $( compgen -f $cur ) )
fi
}

complete -o default -F _my_command nohup exec eval trace truss strace sotruss gdb
complete -o default -F _my_command command type which man nice

# Локальные переменные:
# mode:shell-script
# sh-shell:bash
# Конец:

или

.bash_profile file

Appendix M. Sample .bashrc and .bash_profile Files

The ~/.bashrc file determines the behavior of interactive shells. A good look at this file can lead to a better understanding of Bash.

Emmanuel Rouat contributed the following very elaborate .bashrc file, written for a Linux system. He welcomes reader feedback on it.

Study the file carefully, and feel free to reuse code snippets and functions from it in your own .bashrc file or even in your scripts.

Example M-1. Sample .bashrc file

# =============================================================== #
#
# PERSONAL $HOME/.bashrc FILE for bash-3.0 (or later)
# By Emmanuel Rouat [no-email]
#
# Last modified: Tue Nov 20 22:04:47 CET 2012

# This file is normally read by interactive shells only.
#+ Here is the place to define your aliases, functions and
#+ other interactive features like your prompt.
#
# The majority of the code here assumes you are on a GNU
#+ system (most likely a Linux box) and is often based on code
#+ found on Usenet or Internet.
#
# See for instance:
# tldp.org/LDP/abs/html/index.html
# www.caliban.org/bash
# www.shelldorado.com/scripts/categories.html
# www.dotfiles.org
#
# The choice of colors was done for a shell with a dark background
#+ (white on black), and this is usually also suited for pure text-mode
#+ consoles (no X server available). If you use a white background,
#+ you’ll have to do some other choices for readability.
#
# This bashrc file is a bit overcrowded.
# Remember, it is just just an example.
# Tailor it to your needs.
#
# =============================================================== #

# —> Comments added by HOWTO author.

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

#————————————————————-
# Source global definitions (if any)
#————————————————————-

if [ -f /etc/bashrc ]; then
. /etc/bashrc # —> Read /etc/bashrc, if present.
fi

#—————————————————————
# Automatic setting of $DISPLAY (if not set already).
# This works for me — your mileage may vary….
# The problem is that different types of terminals give
#+ different answers to ‘who am i’ (rxvt in particular can be
#+ troublesome) — however this code seems to work in a majority
#+ of cases.
#—————————————————————

function get_xserver ()
{
case $TERM in
xterm )
XSERVER=$(who am i | awk ‘{print $NF}’ | tr -d ‘)»(‘ )
# Ane-Pieter Wieringa suggests the following alternative:
# I_AM=$(who am i)
# SERVER=${I_AM#*(}
# SERVER=${SERVER%*)}
XSERVER=${XSERVER%%:*}
;;
aterm | rxvt)
# Find some code that works here.…
;;
esac
}

if [ -z ${DISPLAY:=""} ]; then
get_xserver
if [[ -z ${XSERVER} || ${XSERVER} == $(hostname) ||
${XSERVER} == «unix» ]]; then
DISPLAY=":0.0" # Display on local host.
else
DISPLAY=${XSERVER}:0.0 # Display on remote host.
fi
fi

export DISPLAY

#————————————————————-
# Some settings
#————————————————————-

#set -o nounset # These two options are useful for debugging.
#set -o xtrace
alias debug=«set -o nounset; set -o xtrace»

ulimit -S -c 0 # Don’t want coredumps.
set -o notify
set -o noclobber
set -o ignoreeof

# Enable options:
shopt -s cdspell
shopt -s cdable_vars
shopt -s checkhash
shopt -s checkwinsize
shopt -s sourcepath
shopt -s no_empty_cmd_completion
shopt -s cmdhist
shopt -s histappend histreedit histverify
shopt -s extglob # Necessary for programmable completion.

# Disable options:
shopt -u mailwarn
unset MAILCHECK # Don’t want my shell to warn me of incoming mail.

#————————————————————-
# Greeting, motd etc.…
#————————————————————-

# Color definitions (taken from Color Bash Prompt HowTo).
# Some colors might look different of some terminals.
# For example, I see ‘Bold Red’ as ‘orange’ on my screen,
# hence the ‘Green’ ‘BRed’ ‘Red’ sequence I often use in my prompt.

# Normal Colors
Black=’\e[0;30m’ # Black
Red=’\e[0;31m’ # Red
Green=’\e[0;32m’ # Green
Yellow=’\e[0;33m’ # Yellow
Blue=’\e[0;34m’ # Blue
Purple=’\e[0;35m’ # Purple
Cyan=’\e[0;36m’ # Cyan
White=’\e[0;37m’ # White

# Bold
BBlack=’\e[1;30m’ # Black
BRed=’\e[1;31m’ # Red
BGreen=’\e[1;32m’ # Green
BYellow=’\e[1;33m’ # Yellow
BBlue=’\e[1;34m’ # Blue
BPurple=’\e[1;35m’ # Purple
BCyan=’\e[1;36m’ # Cyan
BWhite=’\e[1;37m’ # White

# Background
On_Black=’\e[40m’ # Black
On_Red=’\e[41m’ # Red
On_Green=’\e[42m’ # Green
On_Yellow=’\e[43m’ # Yellow
On_Blue=’\e[44m’ # Blue
On_Purple=’\e[45m’ # Purple
On_Cyan=’\e[46m’ # Cyan
On_White=’\e[47m’ # White

NC="\e[m" # Color Reset

ALERT=${BWhite}${On_Red} # Bold White on red background

echo -e "${BCyan}This is BASH ${BRed}${BASH_VERSION%.*}${BCyan}\
— DISPLAY on ${BRed}$DISPLAY${NC}\n"
date
if [ -x /usr/games/fortune ]; then
/usr/games/fortune -s # Makes our day a bit more fun… 🙂
fi

function _exit() # Function to run upon exit of shell.
{
echo -e "${BRed}Hasta la vista, baby${NC}"
}
trap _exit EXIT

#————————————————————-
# Shell Prompt — for many examples, see:
# www.debian-administration.org/articles/205
# www.askapache.com/linux/bash-power-prompt.html
# tldp.org/HOWTO/Bash-Prompt-HOWTO
# github.com/nojhan/liquidprompt
#————————————————————-
# Current Format: [TIME USER@HOST PWD] >
# TIME:
# Green == machine load is low
# Orange == machine load is medium
# Red == machine load is high
# ALERT == machine load is very high
# USER:
# Cyan == normal user
# Orange == SU to user
# Red == root
# HOST:
# Cyan == local session
# Green == secured remote connection (via ssh)
# Red == unsecured remote connection
# PWD:
# Green == more than 10% free disk space
# Orange == less than 10% free disk space
# ALERT == less than 5% free disk space
# Red == current user does not have write privileges
# Cyan == current filesystem is size zero (like /proc)
# >:
# White == no background or suspended jobs in this shell
# Cyan == at least one background job in this shell
# Orange == at least one suspended job in this shell
#
# Command is added to the history file each time you hit enter,
# so it’s available to all shells (using ‘history -a’).

# Test connection type:
if [ -n "${SSH_CONNECTION}" ]; then
CNX=${Green} # Connected on remote machine, via ssh (good).
elif [[ "${DISPLAY%%:0*}" != "" ]]; then
CNX=${ALERT} # Connected on remote machine, not via ssh (bad).
else
CNX=${BCyan} # Connected on local machine.
fi

# Test user type:
if [[ ${USER} == «root» ]]; then
SU=${Red} # User is root.
elif [[ ${USER} != $(logname) ]]; then
SU=${BRed} # User is not login user.
else
SU=${BCyan} # User is normal (well… most of us are).
fi

NCPU=$(grep -c ‘processor’ /proc/cpuinfo) # Number of CPUs
SLOAD=$(( 100*${NCPU} )) # Small load
MLOAD=$(( 200*${NCPU} )) # Medium load
XLOAD=$(( 400*${NCPU} )) # Xlarge load

# Returns system load as percentage, i.e., ’40’ rather than ‘0.40)’.
function load()
{
local SYSLOAD=$(cut -d " " -f1 /proc/loadavg | tr -d ‘.’)
# System load of the current host.
echo $((10#$SYSLOAD)) # Convert to decimal.
}

# Returns a color indicating system load.
function load_color()
{
local SYSLOAD=$(load)
if [ ${SYSLOAD} -gt ${XLOAD} ]; then
echo -en ${ALERT}
elif [ ${SYSLOAD} -gt ${MLOAD} ]; then
echo -en ${Red}
elif [ ${SYSLOAD} -gt ${SLOAD} ]; then
echo -en ${BRed}
else
echo -en ${Green}
fi
}

# Returns a color according to free disk space in $PWD.
function disk_color()
{
if [! -w "${PWD}" ]; then
echo -en ${Red}
# No ‘write’ privilege in the current directory.
elif [ -s "${PWD}" ]; then
local used=$(command df -P "$PWD" |
awk ‘END {print $5} {sub(/%/,"")}’)
if [ ${used} -gt 95 ]; then
echo -en ${ALERT} # Disk almost full (>95%).
elif [ ${used} -gt 90 ]; then
echo -en ${BRed} # Free disk space almost gone.
else
echo -en ${Green} # Free disk space is ok.
fi
else
echo -en ${Cyan}
# Current directory is size ‘0’ (like /proc, /sys etc).
fi
}

# Returns a color according to running/suspended jobs.
function job_color()
{
if [ $(jobs -s | wc -l) -gt «0» ]; then
echo -en ${BRed}
elif [ $(jobs -r | wc -l) -gt «0» ]; then
echo -en ${BCyan}
fi
}

# Adds some text in the terminal frame (if applicable).

# Now we construct the prompt.
PROMPT_COMMAND=«history -a»
case ${TERM} in
*term | rxvt | linux)
PS1="\[\$(load_color)\][\A\[${NC}\] "
# Time of day (with load info):
PS1="\[\$(load_color)\][\A\[${NC}\] "
# User@Host (with connection type info):
PS1=${PS1}"\[${SU}\]\u\[${NC}\]@\[${CNX}\]\h\[${NC}\] "
# PWD (with ‘disk space’ info):
PS1=${PS1}"\[\$(disk_color)\]\W]\[${NC}\] "
# Prompt (with ‘job’ info):
PS1=${PS1}"\[\$(job_color)\]>\[${NC}\] "
# Set title of current xterm:
PS1=${PS1}"\[\e]0;[\u@\h] \w\a\]"
;;
*)
PS1="(\A \u@\h \W) > " # —> PS1="(\A \u@\h \w) > "
# —> Shows full pathname of current dir.
;;
esac

export TIMEFORMAT=$’\nreal %3R\tuser %3U\tsys %3S\tpcpu %P\n’
export HISTIGNORE="&:bg:fg:ll:h"
export HISTTIMEFORMAT="$(echo -e ${BCyan})[%d/%m %H:%M:%S]$(echo -e ${NC}) "
export HISTCONTROL=ignoredups
export HOSTFILE=$HOME/.hosts # Put a list of remote hosts in ~/.hosts

#============================================================
#
# ALIASES AND FUNCTIONS
#
# Arguably, some functions defined here are quite big.
# If you want to make this file smaller, these functions can
#+ be converted into scripts and removed from here.
#
#============================================================

#——————-
# Personnal Aliases
#——————-

alias rm=’rm -i’
alias cp=’cp -i’
alias mv=’mv -i’
# -> Prevents accidentally clobbering files.
alias mkdir=’mkdir -p’

alias h=’history’
alias j=’jobs -l’
alias which=’type -a’
alias ..=’cd ..’

# Pretty-print of some PATH variables:
alias path=’echo -e ${PATH//:/\\n}’
alias libpath=’echo -e ${LD_LIBRARY_PATH//:/\\n}’

alias du=’du -kh’ # Makes a more readable output.
alias df=’df -kTh’

#————————————————————-
# The ‘ls’ family (this assumes you use a recent GNU ls).
#————————————————————-
# Add colors for filetype and human-readable sizes by default on ‘ls’:
alias ls=’ls -h —color’
alias lx=’ls -lXB’ # Sort by extension.
alias lk=’ls -lSr’ # Sort by size, biggest last.
alias lt=’ls -ltr’ # Sort by date, most recent last.
alias lc=’ls -ltcr’ # Sort by/show change time,most recent last.
alias lu=’ls -ltur’ # Sort by/show access time,most recent last.

# The ubiquitous ‘ll’: directories first, with alphanumeric sorting:
alias ll=«ls -lv —group-directories-first»
alias lm=’ll |more’ # Pipe through ‘more’
alias lr=’ll -R’ # Recursive ls.
alias la=’ll -A’ # Show hidden files.
alias tree=’tree -Csuh’ # Nice alternative to ‘recursive ls’…

#————————————————————-
# Tailoring ‘less’
#————————————————————-

alias more=’less’
export PAGER=less
export LESSCHARSET=’latin1′
export LESSOPEN=’|/usr/bin/lesspipe.sh %s 2>&-‘
# Use this if lesspipe.sh exists.
export LESS=’-i -N -w -z-4 -g -e -M -X -F -R -P%t?f%f \
:stdin .?pb%pb\%:?lbLine %lb:?bbByte %bb:-…’

# LESS man page colors (makes Man pages more readable).
export LESS_TERMCAP_mb=$’\E[01;31m’
export LESS_TERMCAP_md=$’\E[01;31m’
export LESS_TERMCAP_me=$’\E[0m’
export LESS_TERMCAP_se=$’\E[0m’
export LESS_TERMCAP_so=$’\E[01;44;33m’
export LESS_TERMCAP_ue=$’\E[0m’
export LESS_TERMCAP_us=$’\E[01;32m’

#————————————————————-
# Spelling typos — highly personnal and keyboard-dependent 🙂
#————————————————————-

alias xs=’cd’
alias vf=’cd’
alias moer=’more’
alias moew=’more’
alias kk=’ll’

#————————————————————-
# A few fun ones
#————————————————————-

# Adds some text in the terminal frame (if applicable).

function xtitle()
{
case "$TERM" in
*term* | rxvt)
echo -en "\e]0;$*\a" ;;
*) ;;
esac
}

# Aliases that use xtitle
alias top=’xtitle Processes on $HOST && top’
alias make=’xtitle Making $(basename $PWD); make’

#… and functions
function man()
{
for i; do
xtitle The $(basename $1|tr -d .[:digit:]) manual
command man -a "$i"
done
}

#————————————————————-
# Make the following commands run in background automatically:
#————————————————————-

function te() # wrapper around xemacs/gnuserv
{
if [ "$(gnuclient -batch -eval t 2>&-)" == «t» ]; then
gnuclient -q "$@";
else
( xemacs "$@" &);
fi
}

function soffice() { command soffice "$@" & }
function firefox() { command firefox "$@" & }
function xpdf() { command xpdf "$@" & }

#————————————————————-
# File & strings related functions:
#————————————————————-

# Find a file with a pattern in name:
function ff() { find. -type f -iname ‘*’"$*"’*’ -ls; }

# Find a file with pattern $1 in name and Execute $2 on it:
function fe() { find. -type f -iname ‘*’"${1:-}"’*’ \
-exec ${2:-file} {} \;; }

# Find a pattern in a set of files and highlight them:
#+ (needs a recent version of egrep).
function fstr()
{
OPTIND=1
local mycase=""
local usage=«fstr: find string in files.
Usage: fstr [-i] \»pattern\" [\«filename pattern\»] "
while getopts :it opt
do
case "$opt" in
i) mycase="-i " ;;
*) echo "$usage"; return ;;
esac
done
shift $(( $OPTIND — 1 ))
if [ "$#" -lt 1 ]; then
echo "$usage"
return;
fi
find. -type f -name "${2:-*}" -print0 | \
xargs -0 egrep —color=always -sn ${case} "$1" 2>&- | more

}

function swap()
{ # Swap 2 filenames around, if they exist (from Uzi’s bashrc).
local TMPFILE=tmp.$$

[ $# -ne 2 ] && echo «swap: 2 arguments needed» && return 1
[! -e $1 ] && echo «swap: $1 does not exist» && return 1
[! -e $2 ] && echo «swap: $2 does not exist» && return 1

mv "$1" $TMPFILE
mv "$2" "$1"
mv $TMPFILE "$2"
}

function extract() # Handy Extract Program
{
if [ -f $1 ]; then
case $1 in
*.tar.bz2) tar xvjf $1 ;;
*.tar.gz) tar xvzf $1 ;;
*.bz2) bunzip2 $1 ;;
*.rar) unrar x $1 ;;
*.gz) gunzip $1 ;;
*.tar) tar xvf $1 ;;
*.tbz2) tar xvjf $1 ;;
*.tgz) tar xvzf $1 ;;
*.zip) unzip $1 ;;
*.Z) uncompress $1 ;;
*.7z) 7z x $1 ;;
*) echo "’$1′ cannot be extracted via >extract<" ;;
esac
else
echo "’$1′ is not a valid file!"
fi
}

# Creates an archive (*.tar.gz) from given directory.
function maketar() { tar cvzf "${1%%/}.tar.gz" "${1%%/}/"; }

# Create a ZIP archive of a file or folder.
function makezip() { zip -r "${1%%/}.zip" "$1"; }

# Make your directories and files access rights sane.
function sanitize() { chmod -R u=rwX,g=rX,o= "$@" ;}

#————————————————————-
# Process/system related functions:
#————————————————————-

function my_ps() { ps $@ -u $USER -o pid,%cpu,%mem,bsdtime,command; }
function pp() { my_ps f | awk ‘!/awk/ && $0~var’ var=${1:-".*"}; }

function killps() # kill by process name
{
local pid pname sig="-TERM" # default signal
if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then
echo «Usage: killps [-SIGNAL] pattern»
return;
fi
if [ $# = 2 ]; then sig=$1; fi
for pid in $(my_ps| awk ‘!/awk/ && $0~pat { print $1 }’ pat=${!#} )
do
pname=$(my_ps | awk ‘$1~var { print $5 }’ var=$pid )
if ask «Kill process $pid <$pname> with signal $sig?»
then kill $sig $pid
fi
done
}

function mydf() # Pretty-print of ‘df’ output.
{ # Inspired by ‘dfc’ utility.
for fs; do

if [! -d $fs ]
then
echo -e $fs" :No such file or directory"; continue
fi

local info=( $(command df -P $fs | awk ‘END{ print $2,$3,$5 }’) )
local free=( $(command df -Pkh $fs | awk ‘END{ print $4 }’) )
local nbstars=$(( 20 * ${info[1]} / ${info[0]} ))
local out="["
for ((j=0;j<20;j++)); do
if [ ${j} -lt ${nbstars} ]; then
out=$out"*"
else
out=$out"-"
fi
done
out=${info[2]}" "$out"] ("$free" free on "$fs")"
echo -e $out
done
}

function my_ip() # Get IP adress on ethernet.
{
MY_IP=$(/sbin/ifconfig eth0 | awk ‘/inet/ { print $2 } ‘ |
sed -e s/addr://)
echo ${MY_IP:-«Not connected»}
}

function ii() # Get current host related info.
{
echo -e "\nYou are logged on ${BRed}$HOST"
echo -e "\n${BRed}Additionnal information:$NC "; uname -a
echo -e "\n${BRed}Users logged on:$NC "; w -hs |
cut -d " " -f1 | sort | uniq
echo -e "\n${BRed}Current date :$NC "; date
echo -e "\n${BRed}Machine stats :$NC "; uptime
echo -e "\n${BRed}Memory stats :$NC "; free
echo -e "\n${BRed}Diskspace :$NC "; mydf / $HOME
echo -e "\n${BRed}Local IP Address :$NC"; my_ip
echo -e "\n${BRed}Open connections :$NC "; netstat -pan —inet;
echo
}

#————————————————————-
# Misc utilities:
#————————————————————-

function repeat() # Repeat n times command.
{
local i max
max=$1; shift;
for ((i=1; i <= max; i++)); do # —> C-like syntax
eval "$@";
done
}

function ask() # See ‘killps’ for example of use.
{
echo -n "$@" ‘[y/n] ‘; read ans
case "$ans" in
y*|Y*) return 0 ;;
*) return 1 ;;
esac
}

function corename() # Get name of app that created a corefile.
{
for file; do
echo -n $file:; gdb —core=$file —batch | head -1
done
}

#=========================================================================
#
# PROGRAMMABLE COMPLETION SECTION
# Most are taken from the bash 2.05 documentation and from Ian McDonald’s
# ‘Bash completion’ package (http://www.caliban.org/bash/#completion)
# You will in fact need bash more recent then 3.0 for some features.
#
# Note that most linux distributions now provide many completions
# ‘out of the box’ — however, you might need to make your own one day,
# so I kept those here as examples.
#=========================================================================

if [ "${BASH_VERSION%.*}" \< «3.0» ]; then
echo «You will need to upgrade to version 3.0 for full \
programmable completion features»
return
fi

shopt -s extglob # Necessary.

complete -A hostname rsh rcp telnet rlogin ftp ping disk
complete -A export printenv
complete -A variable export local readonly unset
complete -A enabled builtin
complete -A alias alias unalias
complete -A function function
complete -A user su mail finger

complete -A helptopic help # Currently same as builtins.
complete -A shopt shopt
complete -A stopped -P ‘%’ bg
complete -A job -P ‘%’ fg jobs disown

complete -A directory mkdir rmdir
complete -A directory -o default cd

# Compression
complete -f -o default -X ‘*.+(zip|ZIP)’ zip
complete -f -o default -X ‘!*.+(zip|ZIP)’ unzip
complete -f -o default -X ‘*.+(z|Z)’ compress
complete -f -o default -X ‘!*.+(z|Z)’ uncompress
complete -f -o default -X ‘*.+(gz|GZ)’ gzip
complete -f -o default -X ‘!*.+(gz|GZ)’ gunzip
complete -f -o default -X ‘*.+(bz2|BZ2)’ bzip2
complete -f -o default -X ‘!*.+(bz2|BZ2)’ bunzip2
complete -f -o default -X ‘!*.+(zip|ZIP|z|Z|gz|GZ|bz2|BZ2)’ extract

# Documents — Postscript,pdf,dvi…
complete -f -o default -X ‘!*.+(ps|PS)’ gs ghostview ps2pdf ps2ascii
complete -f -o default -X \
‘!*.+(dvi|DVI)’ dvips dvipdf xdvi dviselect dvitype
complete -f -o default -X ‘!*.+(pdf|PDF)’ acroread pdf2ps
complete -f -o default -X ‘!*.@(@(?(e)ps|?(E)PS|pdf|PDF)?\
(.gz|.GZ|.bz2|.BZ2|.Z))’ gv ggv
complete -f -o default -X ‘!*.texi*’ makeinfo texi2dvi texi2html texi2pdf
complete -f -o default -X ‘!*.tex’ tex latex slitex
complete -f -o default -X ‘!*.lyx’ lyx
complete -f -o default -X ‘!*.+(htm*|HTM*)’ lynx html2ps
complete -f -o default -X \
‘!*.+(doc|DOC|xls|XLS|ppt|PPT|sx?|SX?|csv|CSV|od?|OD?|ott|OTT)’ soffice

# Multimedia
complete -f -o default -X \
‘!*.+(gif|GIF|jp*g|JP*G|bmp|BMP|xpm|XPM|png|PNG)’ xv gimp ee gqview
complete -f -o default -X ‘!*.+(mp3|MP3)’ mpg123 mpg321
complete -f -o default -X ‘!*.+(ogg|OGG)’ ogg123
complete -f -o default -X \
‘!*.@(mp[23]|MP[23]|ogg|OGG|wav|WAV|pls|\
m3u|xm|mod|s[3t]m|it|mtm|ult|flac)’ xmms
complete -f -o default -X ‘!*.@(mp?(e)g|MP?(E)G|wma|avi|AVI|\
asf|vob|VOB|bin|dat|vcd|ps|pes|fli|viv|rm|ram|yuv|mov|MOV|qt|\
QT|wmv|mp3|MP3|ogg|OGG|ogm|OGM|mp4|MP4|wav|WAV|asx|ASX)’ xine

complete -f -o default -X ‘!*.pl’ perl perl5

# This is a ‘universal’ completion function — it works when commands have
#+ a so-called ‘long options’ mode, ie: ‘ls —all’ instead of ‘ls -a’
# Needs the ‘-o’ option of grep
#+ (try the commented-out version if not available).

# First, remove ‘=’ from completion word separators
#+ (this will allow completions like ‘ls —color=auto’ to work correctly).

COMP_WORDBREAKS=${COMP_WORDBREAKS/=/}

_get_longopts()
{
#$1 —help | sed -e ‘/—/!d’ -e ‘s/.*—\([^[:space:].,]*\).*/—\1/’| \
#grep ^"$2" |sort -u;
$1 —help | grep -o -e "—[^[:space:].,]*" | grep -e "$2" |sort -u
}

_longopts()
{
local cur
cur=${COMP_WORDS[COMP_CWORD]}

case "${cur:-*}" in
-*) ;;
*) return ;;
esac

case "$1" in
\~*) eval cmd="$1" ;;
*) cmd="$1" ;;
esac
COMPREPLY=( $(_get_longopts ${1} ${cur} ) )
}
complete -o default -F _longopts configure bash
complete -o default -F _longopts wget id info a2ps ls recode

_tar()
{
local cur ext regex tar untar

COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}

# If we want an option, return the possible long options.
case "$cur" in
-*) COMPREPLY=( $(_get_longopts $1 $cur ) ); return 0;;
esac

if [ $COMP_CWORD -eq 1 ]; then
COMPREPLY=( $( compgen -W ‘c t x u r d A’ — $cur ) )
return 0
fi

case "${COMP_WORDS[1]}" in
?(-)c*f)
COMPREPLY=( $( compgen -f $cur ) )
return 0
;;
+([^Izjy])f)
ext=’tar’
regex=$ext
;;
*z*f)
ext=’tar.gz’
regex=’t\(ar\.\)\(gz\|Z\)’
;;
*[Ijy]*f)
ext=’t?(ar.)bz?(2)’
regex=’t\(ar\.\)bz2\?’
;;
*)
COMPREPLY=( $( compgen -f $cur ) )
return 0
;;

esac

if [[ "$COMP_LINE" == tar*.$ext’ ‘* ]]; then
# Complete on files in tar file.
#
# Get name of tar file from command line.
tar=$( echo "$COMP_LINE" | \
sed -e ‘s|^.* \([^ ]*’$regex’\) .*$|\1|’ )
# Devise how to untar and list it.
untar=t${COMP_WORDS[1]//[^Izjyf]/}

COMPREPLY=( $( compgen -W "$( echo $( tar $untar $tar \
2>/dev/null ) )" — "$cur" ) )
return 0

else
# File completion on relevant files.
COMPREPLY=( $( compgen -G $cur\*.$ext ) )

fi

return 0

}

complete -F _tar -o default tar

_make()
{
local mdef makef makef_dir="." makef_inc gcmd cur prev i;
COMPREPLY=();
cur=${COMP_WORDS[COMP_CWORD]};
prev=${COMP_WORDS[COMP_CWORD-1]};
case "$prev" in
-*f)
COMPREPLY=($(compgen -f $cur ));
return 0
;;
esac;
case "$cur" in
-*)
COMPREPLY=($(_get_longopts $1 $cur ));
return 0
;;
esac;

#… make reads
# GNUmakefile,
# then makefile
# then Makefile…
if [ -f ${makef_dir}/GNUmakefile ]; then
makef=${makef_dir}/GNUmakefile
elif [ -f ${makef_dir}/makefile ]; then
makef=${makef_dir}/makefile
elif [ -f ${makef_dir}/Makefile ]; then
makef=${makef_dir}/Makefile
else
makef=${makef_dir}/*.mk # Local convention.
fi

# Before we scan for targets, see if a Makefile name was
#+ specified with -f.
for (( i=0; i < ${#COMP_WORDS[@]}; i++ )); do
if [[ ${COMP_WORDS[i]} == -f ]]; then
# eval for tilde expansion
eval makef=${COMP_WORDS[i+1]}
break
fi
done
[! -f $makef ] && return 0

# Deal with included Makefiles.
makef_inc=$( grep -E ‘^-?include’ $makef |
sed -e «s,^.* ,»$makef_dir"/," )
for file in $makef_inc; do
[ -f $file ] && makef="$makef $file"
done

# If we have a partial word to complete, restrict completions
#+ to matches of that word.
if [ -n "$cur" ]; then gcmd=’grep "^$cur"’; else gcmd=cat; fi

COMPREPLY=( $( awk -F’:’ ‘/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ \
{split($1,A,/ /);for(i in A)print A[i]}’ \
$makef 2>/dev/null | eval $gcmd ))

}

complete -F _make -X ‘+($*|*.[cho])’ make gmake pmake

_killall()
{
local cur prev
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}

# Get a list of processes
#+ (the first sed evaluation
#+ takes care of swapped out processes, the second
#+ takes care of getting the basename of the process).
COMPREPLY=( $( ps -u $USER -o comm | \
sed -e ‘1,1d’ -e ‘s#[]\[]##g’ -e ‘s#^.*/##’| \
awk ‘{if ($0 ~ /^’$cur’/) print $0}’ ))

return 0
}

complete -F _killall killall killps

# Local Variables:
# mode:shell-script
# sh-shell:bash
# End:
And, here is a snippet from Andrzej Szelachowski’s instructive .bash_profile file.

Example M-2. .bash_profile file

# From Andrzej Szelachowski’s ~/.bash_profile:

# Note that a variable may require special treatment
#+ if it will be exported.

DARKGRAY=’\e[1;30m’
LIGHTRED=’\e[1;31m’
GREEN=’\e[32m’
YELLOW=’\e[1;33m’
LIGHTBLUE=’\e[1;34m’
NC=’\e[m’

PCT="\`if [[ \$EUID -eq 0 ]]; then T=’$LIGHTRED’; else T=’$LIGHTBLUE’; fi;
echo \$T \`"

# For «literal» command substitution to be assigned to a variable,
#+ use escapes and double quotes:
#+ PCT="\`… \`"…
# Otherwise, the value of PCT variable is assigned only once,
#+ when the variable is exported/read from .bash_profile,
#+ and it will not change afterwards even if the user ID changes.

PS1="\n$GREEN[\w] \n$DARKGRAY($PCT\t$DARKGRAY)-($PCT\u$DARKGRAY)-($PCT\!
$DARKGRAY)$YELLOW-> $NC"

# Escape a variables whose value changes:
# if [[ \$EUID -eq 0 ]],
# Otherwise the value of the EUID variable will be assigned only once,
#+ as above.

# When a variable is assigned, it should be called escaped:
#+ echo \$T,
# Otherwise the value of the T variable is taken from the moment the PCT
#+ variable is exported/read from .bash_profile.
# So, in this example it would be null.

# When a variable’s value contains a semicolon it should be strong quoted:
# T=’$LIGHTRED’,
# Otherwise, the semicolon will be interpreted as a command separator.

# Variables PCT and PS1 can be merged into a new PS1 variable:

PS1="\`if [[ \$EUID -eq 0 ]]; then PCT=’$LIGHTRED’;
else PCT=’$LIGHTBLUE’; fi;
echo ‘\n$GREEN[\w] \n$DARKGRAY(‘\$PCT’\t$DARKGRAY)-\
(‘\$PCT’\u$DARKGRAY)-(‘\$PCT’\!$DARKGRAY)$YELLOW-> $NC’\`"

# The trick is to use strong quoting for parts of old PS1 variable.

Как оказывается это выход, однако, Вы имеете много гибкости на то, что Вы вкладываете в эту подсказку.

Основная подсказка PS1 может быть установлена в интерактивном режиме, но как правило устанавливается в один из Ваших точечных файлов. По умолчанию, как правило только в "$", но некоторые администраторы настроят это, чтобы включить такие вещи, как имя системы или Ваше текущее местоположение в файловой системе. Что не нравится? Отвергните его в «seeintgs» или Ваш собственный. По умолчанию, как правило, просто знак ">".

Вы также можете установить команду PS2 — изменения пути Ваших подсказок когда Вы в “петле”. Вы можете вывести это значение через команду “echo \”.

# echo \ >  

Ваши подсказки должны быть установлены для обеспечения наиболее интересного или полезного индикатора. Не могу вспомнить, какой сегодня день? Установите Ваши подсказки по дате:

PS1='\d>' Tue Dec 22> 

Хотите быть уверены что Вы не хотите забыть сколько времени и в конечном итоге работаете до полуночи? Установите Вашу подсказку с текущем временем.

Tue Dec 22>PS1="\@> " 08:55 AM> 

А также, Вы можете установить в свои подсказки — секунды. Это может быть полезно если Вы хотите почувствовать, как долго отдельные команды, которые Вы запускаете принимают обработку.

08:58 AM> PS1="\D{}> " 08:59:01 AM>  

Если Вы предпочитаете 24-часовой формат, используйте “\A” или “\t”.

08:59:01 AM> PS1="\A> " 09:10>  09:10> PS1="\t> " 09:10:36> 

Примечание: “>” в конце эти подсказки и пробел, как дополнение, но это мое предпочтение. Мне нравятся эти символы, отделяющиеся мою подсказку от моих команд. Есть проблема с запоминанием, что Вы вошли в систему?

lw1777PS1='\h ' lw1777 

Хотите плохо себя чувствовать, потому что Вам требуется столько команд, чтобы выполнить задачу?

lw1777 PS1='\# ' 22 

Используйте! Если Вы хотите увидеть, где Вы находитесь по отношению к Вашей истории буфера.

22> PS1='\!> ' 234> 

Если Вы не можете вспомнить где Вы находитесь “w” установка покажет Ваш путь относительно домашней директории.

PS1='\w ' ~ 

Когда Вы нуждаетесь в некотором подбадривание:

$ PS1=':-) ' :-) 

Когда Вы имеете амнезию или просто хотите, чтобы напомнить, в какой аккаунт Вы вошли:

PS1="\u> " lmoore> 

Вы можете расширить это, чтобы показать имя пользователя и имя системы как это:

PS1="\u@\h " PS1="\u@\h " root@lw1777 

Любое следующие может быть использовано “din” Вашей подсказкой, хотя я полагаю что мало из нас будет слышать колокол даже если мы используем образ струны в нашей подсказке.

\a     an ASCII bell character (07) \d     the date  in  "Weekday  Month  Date"  format (e.g.,       "Tue May 26") \e     an ASCII escape character (033) \h     the hostname up to the first `.' \H     the hostname \j     the  number of jobs currently managed by the shell \l     the basename of the shell's terminal  device name \n     newline \r     carriage return \s     the  name  of  the shell, the basename of $0 (the       portion following the final slash) \t     the current time in 24-hour HH:MM:SS format \T     the current time in 12-hour HH:MM:SS format \@     the current time in 12-hour am/pm format \u     the username of the current user \v     the version of bash (e.g., 2.00) \V     the release of bash,  version  +  patch level (e.g.,       2.00.0) \w     the current working directory \W     the  basename  of the current working directory \!     the history number of this command \#     the command number of this command \$     if the effective UID is 0, a #, otherwise a $ \nnn   the  character  corresponding  to  the octal number nnn \\     a backslash \[     begin a sequence of non-printing characters, which could       be used to embed a terminal control        sequence into the prompt \]     end a sequence of non-printing characters 

Вы также можете поместить другую информацию на Вашу подсказку, но есть одна загвоздка. Если Вы используете одну с bash подсказок, избежать последовательности (like \d and \@), подсказка устанавливается при определении PS1 и не обновляется. Установка PS1 для вывода даты команды и Ваша подсказка будет показывать дату и время, пока Вы не выйдете с системы.

root@lw1777 PS1="`date`> " Tue Dec 22 11:26:58 UTC 2015> 

Если Вы чувствуете себя подавленным, Вы можете даже изменить цвет своей подсказки:

Tue Dec 22 11:26:58 UTC 2015> PS1="\e[34m\]u@\h " u@lw1777 

Возможно использовать много других цветов:

30m: Black 31m: Red 32m: Green 33m: Yellow 34m: Blue 35m: Purple 36m: Cyan 7m: White 

Вы можете даже использовать несколько цветов в одной подсказке, выполнив что-то вроде этого:

u@lw1777 PS1=`\[\e[0;31m\]\u\[\e[m\] \[\e[1;35m\]\w\[\e[m\]> ` 

Примечание: “\[ и \]” вокруг цветовых кодов. Вы также можете изменять шрифты, которые Вы используете, как в примерах что показаны ниже:

0=regular 0;31m 1=bold 1:35m 4=underline 4:32m 

Вот привлекательный маленький трюк предлагает Ваша подсказка. Вы можете поставить текущее время в правом угле окна терминала и изменить Вашу подсказку ">" с такой настройкой:

[root@lw1777 ~]# PS1="> \[\033[s\]\[\033[1;\$((COLUMNS-4))f\]\$(date +%H:%M)\[\033[u\]\" 

Или, если вы предпочитаете, отображение дня недели:

[root@lw1777 ~]# PS1="> \[\033[s\]\[\033[1;\$((COLUMNS-8))f\]\$(date +%A)\[\033[u\]" 

Система подсказок не самая захватывающая часть работы в командной строке Unix, но они обеспечивают полезную информацию если Вы не торопитесь чтобы настроить их.

ссылка на оригинал статьи http://habrahabr.ru/post/267143/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *