پیوست ‎M‎- فایل‌های نمونه ‎.bashrc‎ و ‎.bash_profile‎

فایل ‎~/.bashrc‎ رفتار پوسته‌های محاوره‌ای را تعیین می‌کند. یک نگاه شایسته به این فایل می‌تواند منجر به درک بهتری از Bash بشود.

‎Emmanuel Rouat‎ فایل ‎.bashrc‎ دارای جزییات بسیار زیاد پایین، نوشته شده برای یک سیستم لینوکس را اهدا نموده است.

فایل را به دقت مطالعه کنید، و با خیال راحت قطعه کدها و توابع آن را در فایل ‎.bashrc‎ خودتان یا حتی در اسکریپت‌هایتان استفاده نمایید.

مثال ‎M-1‎. فایل نمونه ‎.bashrc‎

# ================================================================ #
#
#              فایل شخصی ‎$HOME/.bashrc‎ برای ‎bash-3.0‎ (یا بعد از آن)
#                                    توسط ‎Emmanuel Rouat [no-email]‎
#
#                        آخرین ویرایش: ‎Tue Nov 20 22:04:47 CET 2012‎

# این فایل به طور عادی فقط به وسیله پوسته‌های محاوره‌ای خوانده می‌شود.
#+  محلی است که مستعارها، توابع و سایر ویژگی‌های محاوره‌ای مانند اعلان
#+                                    فرمان پوسته شما تعریف می‌شوند.
#
# بیشتر کد مندرج در آن فرض می‌کند که شما روی یک سیستم گنو (به احتمال
#+  بسیار یک ‎Linux box‎) هستید و اکثر بخش‌های آن بر اساس کدهای مشاهده
#+                                    شده در Usenet یا اینترنت است.
#
#                                   برای نمونه موارد زیر را ببینید:
#  http://tldp.org/LDP/abs/html/index.html
#  http://www.caliban.org/bash
#  http://www.shelldorado.com/scripts/categories.html
#  http://www.dotfiles.org
#
# انتخاب رنگها برای یک پوسته با پس‌زمینه تاریک (سفید روی سیاه) انجام
#+  شده است، و این معمولاً برای وضعیت متن خالص کنسول‌ها (نه سرویس‌دهنده
#+  ‎X‎ موجود) نیز مناسب است. اگر شما از پس‌زمینه سفید استفاده می‌کنید،
#+             برای خوانایی بهتر باید انتخاب‌های دیگری به عمل آورید.
#
#                               این فایل ‎bashrc‎ کمی زیادی شلوغ است.
#  به خاطر داشته باشید که فقط فقط یک مثال است. به تناسب نیازهای خود
#                                              آن را ویرایش نمایید.
#
# ================================================================= #

#-->       توضیحات اضافه شده به وسیله نویسنده HOWTO.

# اگر در وضعیت محاوره‌ای اجرا نشود، کاری انجام نمی‌دهد
[ -z "$PS1" ] && return


# -------------------------------------------------------------
#         منبع کردن تعاریف سراسری (اگر موجود باشد)
# -------------------------------------------------------------


if [ -f /etc/bashrc ]; then
      . /etc/bashrc   # -->خواندن فایل ‎/etc/bashrc‎ اگر باشد.
fi


# --------------------------------------------------------------
#                 تنظیم خوکار ‎$DISPLAY‎ (اگر از قبل تنظیم نباشد).
# این برای من کار می‌کند - در مورد شما ممکن است متفاوت باشد . . .
# مشکل آن است که انواع متفاوت ترمینال‌ پاسخ‌های مختلفی به ‎who am i‎
#+ می‌دهند (مخصوصا ‎rxvt‎ می‌تواند دردسر آفرین باشد) - به هر حال این
#+                          کد ظاهراً با اکثریت موارد کار می‌کند.
# --------------------------------------------------------------

function get_xserver ()
{
    case $TERM in
        xterm )
            XSERVER=$(who am i | awk '{print $NF}' | tr -d ')''(' )
            #  ‎Ane-Pieter Wieringa‎ جایگزین زیر را پیشنهاد می‌کند:
            # I_AM=$(who am i)
            # SERVER=${I_AM#*(}
            # SERVER=${SERVER%*)}
            XSERVER=${XSERVER%%:*}
            ;;
            aterm | rxvt)
            #          مقداری کد بیابید که در اینجا کار کند. ...
            ;;
    esac
}

if [ -z ${DISPLAY:=""} ]; then
    get_xserver
    if [[ -z ${XSERVER}  || ${XSERVER} == $(hostname) ||
       ${XSERVER} == "unix" ]]; then
          DISPLAY=":0.0"          #     ‎Display‎ روی میزبان محلی.
    else
       DISPLAY=${XSERVER}:0.0     #  ‎Display‎ روی میزبان راه دور.
    fi
fi

export DISPLAY

# --------------------------------------------------------------
#                   برخی تنظیمات
# --------------------------------------------------------------

# set -o nounset    #اینها دو انتخاب مفید برای اشکالزدابی هستند.
# set -o xtrace
alias debug="set -o nounset; set -o xtrace"

ulimit -S -c 0      # تهیه فایل‌های ‎core‎ ‏(رونوشت حافظه) لازم نیست.
set -o notify
set -o noclobber
set -o ignoreeof


#      فعال کردن گزینه‌ها:
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      #      برای تکمیل قابل برنامه‌ریزی لازم است.

#  از کار انداختن گزینه‌ها:
shopt -u mailwarn
unset MAILCHECK       # لازم نیست پوسته mail وارده را اطلاع بدهد.


# --------------------------------------------------------------
#               پیغام خوشامدگویی، و غیره ...
# --------------------------------------------------------------

#              تعاریف رنگ (بر گرفته از اعلان ‎Bash رنگی در ‎HowTo‎)‏.
#             برخی رنگ‌ها ممکن است در ترمینال‌ها متفاوت دیده شوند.
#           برای مثال، من قرمز ضخیم را در نمایشگرم نارنجی می‌بینم
# از اینرو اغلب توالی Green، BRed، Red را در اعلانم به کار می‌برم.


# رنگ‌های عادی
Black='\e[0;30m'        #     سیاه
Red='\e[0;31m'          #     قرمز
Green='\e[0;32m'        #      سبز
Yellow='\e[0;33m'       #      زرد
Blue='\e[0;34m'         #      آبی
Purple='\e[0;35m'       #    زرشکی
Cyan='\e[0;36m'         # فیروزه‌ای
White='\e[0;37m'        #     سفید

#   ضخیم
BBlack='\e[1;30m'       #     سیاه
BRed='\e[1;31m'         #     قرمز
BGreen='\e[1;32m'       #      سبز
BYellow='\e[1;33m'      #      زرد
BBlue='\e[1;34m'        #      آبی
BPurple='\e[1;35m'      #    زرشکی
BCyan='\e[1;36m'        # فیروزه‌ای
BWhite='\e[1;37m'       #     سفید

#  پس‌زمینه
On_Black='\e[40m'       #     سیاه
On_Red='\e[41m'         #     قرمز
On_Green='\e[42m'       #      سبز
On_Yellow='\e[43m'      #      زرد
On_Blue='\e[44m'        #      آبی
On_Purple='\e[45m'      #    زرشکی
On_Cyan='\e[46m'        # فیروزه‌ای
On_White='\e[47m'       #     سفید

NC="\e[m"               # بازنشانی رنگ


ALERT=${BWhite}${On_Red} # سفید ضخیم روی پس‌زمینه قرمز



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     # روزمان را قدری مفرح‌تر می‌کند.... :-)
fi

function _exit()              # تابعی جهت اجرا به محض خروج از پوسته
{
    echo -e "${BRed}Hasta la vista, baby${NC}"
}
trap _exit EXIT

# -------------------------------------------------------------
#    اعلان پوسته - برای نمونه‌های زیاد، موارد زیر را ببینید:
#    http://www.debian-administration.org/articles/205
#    http://www.askapache.com/linux/bash-power-prompt.html
#    http://tldp.org/HOWTO/Bash-Prompt-HOWTO
#    https://github.com/nojhan/liquidprompt
# -------------------------------------------------------------
# Current Format: ‎[TIME USER@HOST PWD] >‎
#                    TIME:
#    سبز           == بارگیری ماشین پایین است
#    نارنجی        == بارگیری ماشین متوسط است
#    قرمز          ==     بارگیری ماشین بالاست
#    سفید روی قرمز ==      بارگیری خیلی بالاست
#                    USER:
#                 فیروزه‌ای    ==   کاربر عادی
#                 نارنجی      ==  SU به کاربر
#                 قرمز        ==   کاربر ‎root‎
#                    HOST:
#                     فیروزه‌ای   == نشست محلی
# سبز        == اتصال راه‌دور امن(از طریق ssh)
#          قرمز       == اتصال راه دور نا امن
#                     PWD:
# سبز           ==  فضای خالی بیش از ‎10%‎ دیسک
# نارنجی        == فضای خالی کمتر از ‎10%‎ دیسک
# سفید روی قرمز ==  فضای خالی کمتر از ‎5%‎ دیسک
# قرمز    == کاربر جاری فاقد امتیاز نوشتن است
# فیروزه‌ای  == اندازه سیستم فایل جاری صفر است (مانند ‎/proc‎)
#                      >:
# سفید       == هیچ ‎job‎ پس‌زمینه یا تعلیقی در این پوسته نیست
# فیروزه‌ای   ==       حداقل یک ‎job‎ پس‌زمینه در این پوسته هست
# نارنجی     ==        حداقل یک ‎job‎ تعلیقی در این پوسته هست
#
# وقتی شما اینتر را بزنید فرمان به فایل تاریخچه اضافه می‌شود
#پس برای تمام پوسته‌ها معتبر است (با استفاده از ‎history -a‎).


#             تست نوع ارتباط:
if [ -n "${SSH_CONNECTION}" ]; then
    CNX=${Green}        #  متصل روی ماشین راه دور (از طریق ssh) (خوب).
elif [[ "${DISPLAY%%:0*}" != "" ]]; then
    CNX=${ALERT}        # متصل در ماشین راه دور ، نه از طریق ssh (بد).
else
    CNX=${BCyan}        #                         متصل روی ماشین محلی.
fi

#              تست نوع کاربر:
if [[ ${USER} == "root" ]]; then
    SU=${Red}           #                 کاربر root است.
elif [[ ${USER} != $(logname) ]]; then
    SU=${BRed}          #      کاربر، یک کاربر لاگین نیست.
else
    SU=${BCyan}         # کاربر عادی (خب، اکثر ما هستیم).
fi



NCPU=$(grep -c 'processor' /proc/cpuinfo)   # تعداد CPU
SLOAD=$(( 100*${NCPU} ))            #     بارگیری آهسته
MLOAD=$(( 200*${NCPU} ))            #     بارگیری متوسط
XLOAD=$(( 400*${NCPU} ))            # بارگیری خیلی زیاد

# بارگیری سیستم را برحسب درصد برگشت می‌دهد، مثلاً ‎40‎ به جای ‎0.40
function load()
{
    local SYSLOAD=$(cut -d " " -f1 /proc/loadavg | tr -d '.')
    # بارگیری سیستم میزبان جاری.
    echo $((10#$SYSLOAD))       # تبدیل به دسیمال.
}

#      یک رنگ نشان‌دهنده بارگیری سیستم برگشت می‌دهد.
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
}

# یک رنگ متناسب با فضای خالی دیسک در ‎$PWD‎ برگشت می‌دهد.
function disk_color()
{
    if [ ! -w "${PWD}" ] ; then
        echo -en ${Red}
            # فاقد امتیاز نوشتن در دایرکتوری جاری است.
    elif [ -s "${PWD}" ] ; then
        local used=$(command df -P "$PWD" |
                   awk 'END {print $5} {sub(/%/,"")}')
        if [ ${used} -gt 95 ]; then
            echo -en ${ALERT}           #      دیسک تقریبا پُر است ‎(>95%)‎.
        elif [ ${used} -gt 90 ]; then
            echo -en ${BRed}            # فضای خالی دیسک تقریبا تمام شده.
        else
            echo -en ${Green}           #       فضای خالی دیسک مناسب است.
        fi
    else
        echo -en ${Cyan}
        # اندازه دایرکتوری جاری صفر است (مانند ‎/proc‎،‏ ‎/sys‎ و غیره).
    fi
}

# متناسب با jobهای در حال اجرا یا معلق، یک رنگ برگشت می‌دهد.
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
}

# مقداری متن به کالبد ترمینال اضافه می‌کند (اگر شدنی باشد).


#            اکنون ما اعلان را ایجاد می‌کنیم.
PROMPT_COMMAND="history -a"
case ${TERM} in
  *term | rxvt | linux)
        PS1="\[\$(load_color)\][\A\[${NC}\] "
        #         ساعت (با اطلاعات بارگیری):
        PS1="\[\$(load_color)\][\A\[${NC}\] "
        # ‎User@Host‎ (با اطلاعات نوع ارتباط):
        PS1=${PS1}"\[${SU}\]\u\[${NC}\]@\[${CNX}\]\h\[${NC}\] "
        #   ‎PWD‎ (با اطلاعات فضای خالی دیسک):
        PS1=${PS1}"\[\$(disk_color)\]\W]\[${NC}\] "
        #             اعلان (با اطلاعات job):
        PS1=${PS1}"\[\$(job_color)\]>\[${NC}\] "
        #           تنظیم عنوان xterm جاری:
        PS1=${PS1}"\[\e]0;[\u@\h] \w\a\]"
        ;;
    *)
        PS1="(\A \u@\h \W) > " # --> PS1="(\A \u@\h \w) > "
                               # -->نام مسیر کامل شاخه جاری را نمایش می‌دهد.
        ;;
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    # لیستی از میزبان‌های راه دور در ‎~/.hosts‎ قرار بدهید


# ============================================================
#
#                        مستعارها و توابع
#
# شاید برخی از توابع تعریف شده در اینجا واقعاً بزرگ باشند.
# اگر شما مایل هستید این فایل را کوچکتر کنید، می‌توانید این
#+  توابع را به اسکریپت تبدیل نموده و از اینجا حذف نمایید.
#
# ============================================================

# -------------------
#   مستعارهای شخصی
# -------------------

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
# -> از پاک کردن اتفاقی فایل پیش‌گیری می‌کند.
alias mkdir='mkdir -p'

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

# چاپ شکیل متغیرهای PATH:
alias path='echo -e ${PATH//:/\\n}'
alias libpath='echo -e ${LD_LIBRARY_PATH//:/\\n}'


alias du='du -kh'    # خروجی خواناتری تولید می‌کند.
alias df='df -kTh'

# -----------------------------------------------------------------------
#    خانواده ls (این مستعارها مبتنی بر استفاده از نگارش جدید ls گنو است).
# -----------------------------------------------------------------------
#           افزودن رنگ برای نوع فایل و اندازه‌های خوانای فایل به خروجی ls:
alias ls='ls -h --color'
alias lx='ls -lXB'     #                  مرتب کردن نسبت به پسوند فایل‌ها.
alias lk='ls -lSr'     #       مرتب کردن برحسب اندازه، بزرگترین در انتها.
alias lt='ls -ltr'     #     مرتب نمودن به نسبت تاریخ، جدیدترین در انتها.
alias lc='ls -ltcr'    #  مرتب‌سازی به نسبت زمان تغییر/،جدیدترین در انتها.
alias lu='ls -ltur'    # مرتب کردن به نسبت زمان دستیابی، جدیدترین در آخر.

#   ll همه جا حاضر: نخست دایرکتوری‌ها، با مرتب‌سازی الفبایی:
alias ll="ls -lv --group-directories-first"
alias lm='ll |more'        #        لوله‌کشی به برنامه more
alias lr='ll -R'           #                   ls بازگشتی.
alias la='ll -A'           #          نمایش فایل‌های پنهان.
alias tree='tree -Csuh'    # جایگزین خوبی برای 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:-...'

#      رنگ‌های صفحه man فرمان less (صفحه‌های man را خواناتر می‌سازد).
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'


# -------------------------------------------------------------
# اشتباهات تایپی - به شذت شخصی و مبتنی بر صفحه کلید :-)
# -------------------------------------------------------------

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


# -------------------------------------------------------------
#                      چند مورد جالب
# -------------------------------------------------------------

# اضافه کردن مقداری متن به کالبد ترمینال (اگر مقدور باشد).

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


# مستعارهایی که xtitle را به کار می‌برند
alias top='xtitle Processes on $HOST && top'
alias make='xtitle Making $(basename $PWD) ; make'

#      .. و توابع
function man()
{
    for i ; do
        xtitle The $(basename $1|tr -d .[:digit:]) manual
        command man -a "$i"
    done
}


# -------------------------------------------------------------
# خودکار سازی اجرا در پس‌زمینه برای فرمان‌های زیر:
# -------------------------------------------------------------

function te()  # بسته‌بندی در اطراف ‎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 "$@" & }


# -------------------------------------------------------------
#               توابع مرتبط بافایل و رشته‌ها:
# -------------------------------------------------------------


#                     جستجوی یک فایل با الگویی در نام:
function ff() { find . -type f -iname '*'"$*"'*' -ls ; }

# جستجوی یک فایل با الگوی ‎$1‎ در نام و اجرای ‎$2‎ روی آن:
function fe() { find . -type f -iname '*'"${1:-}"'*' \
-exec ${2:-file} {} \;  ; }

# جستجوی یک الگو در یک مجموعه فایل و برجسته کردن آنها:
#+                  (نیازمند نگارش‌های جدید 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()
{ # معاوضه نام دو فایل، اگر موجود باشند (از bashrc تنظیم ‎Uzi‎).
    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()      # برنامه سودمند استخراج
{
    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
}


# یک بایگانی ‎(*.tar.gz)‎ از دایرکتوری تعیین شده ایجاد می‌کند.
function maketar() { tar cvzf "${1%%/}.tar.gz"  "${1%%/}/"; }

#       یک بایگانی ‎ZIP‎ از یک فایل یا دایرکتوری تولید می‌کند.
function makezip() { zip -r "${1%%/}.zip" "$1" ; }

#       دسترسی به فایل‌ها و دایرکتوری‌های شما را معقول می‌کند.
function sanitize() { chmod -R u=rwX,g=rX,o= "$@" ;}

# -------------------------------------------------------------
#              توابع مرتبط با ‎Process/system‎:
# -------------------------------------------------------------


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 به وسیله نام پردازش
{
    local pid pname sig="-TERM"     # سیگنال پیش‌فرض
    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()         #  چاپ شکیل خروجی df
{                       # ملهم از برنامه dfc
    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() #     به دست آوردن آدرس ‎IP‎ روی اترنت.
{
    MY_IP=$(/sbin/ifconfig eth0 | awk '/inet/ { print $2 } ' |
      sed -e s/addr://)
    echo ${MY_IP:-"Not connected"}
}

function ii()   # به دست آوردن اطلاعات مربوط به میزبان.
{
    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
}

# -------------------------------------------------------------
#                    برنامه‌های سودمند متفرقه:
# -------------------------------------------------------------

function repeat()       # ‎n‎ مرتبه تکرار فرمان.
{
    local i max
    max=$1; shift;
    for ((i=1; i <= max ; i++)); do    # -->  ترکیب دستوری سبک C
        eval "$@";
    done
}


function ask()     # برای مثال کاربرد آن، تابع ‎killps‎ را ببینید.
{
    echo -n "$@" '[y/n] ' ; read ans
    case "$ans" in
        y*|Y*) return 0 ;;
        *) return 1 ;;
    esac
}

function corename()    # کسب نام برنامه تولید کننده یک فایل core
{
    for file ; do
        echo -n $file : ; gdb --core=$file --batch | head -1
    done
}


# =========================================================================
#
#                        بخش تکمیل قابل برنامه‌ریزی
# بیشتر از مستندات ‎bash 2.05‎ و از بسته «‎Bash completion‎» نوشته ‎Ian McDonald‎
#                  (‎http://www.caliban.org/bash/#completion‎) اخذ گردیده است
#   در واقع برای برخی ویژگی‌ها شما به ‎bash‎ جدیدتر از نگارش ‎3.0‎ احتیاج دارید.
#
#   توجه کنید که اکنون اکثر توزیع‌های لینوکس تکمیل‌های بسیاری را به طور آماده
#  ارایه می‌کنند - به هر حال ممکن است یک روز احتیاج داشته باشید خودتان آن را
#        انجام بدهید، بنابراین آنها را به عنوان نمونه در اینجا داشته باشید.
# =========================================================================

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        # ضروری است.

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     # به طور جاری مانند داخلی‌ها.
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
complete -f -o default -X '!*.+(zip|ZIP|z|Z|gz|GZ|bz2|BZ2)' extract

# مستندات - ‎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

#   چند رسانه‌ای
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

# این یک تابع تکمیل همگانی است - وقتی کار می‌کند که فرمان دارای
#+  وضعیت «گزینه‌های بلند» یعنی: ‎'ls --all'‎ به جای ‎'ls -a'‎ باشد
#                              به گزینه ‎-o‎ برای grep نیاز دارد
#+ (در صورتیکه معتبر نبود نگارش توضیحی شده آن را امتحان کنید).

#اول = را از جداکننده‌های کلمه تکمیل حذف کنید (این به تکمیل‌هایی
#+  مانند ‎'ls --color=auto'‎ اجازه می‌دهد به طور صحیح کار کنند).

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]}

    # اگر یک گزینه بخواهیم، گزینه‌های بلند محتمل برگشت داده می‌شوند.
    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
        #     تکمیل فایل‌ها روی فایل tar.
        #
        #  کسب نام فایل tar از خط فرمان.
        tar=$( echo "$COMP_LINE" | \
                        sed -e 's|^.* \([^ ]*'$regex'\) .*$|\1|' )
        #  تعبیه چگونگی untar و لیست آن.
        untar=t${COMP_WORDS[1]//[^Izjyf]/}

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

    else
        # تکمیل فایل روی فایل‌های وابسته.
        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         # قرار داد محلی.
    fi

    # قبل از اینکه فایل‌های مقصد را پویش کنیم، دیدن آنکه
    #+          آیا یک نام Makefile با ‎-f‎ مشخص شده است.
    for (( i=0; i < ${#COMP_WORDS[@]}; i++ )); do
        if [[ ${COMP_WORDS[i]} == -f ]]; then
            # ‎eval‎ برای بسط ~ ‏(مد)‏
            eval makef=${COMP_WORDS[i+1]}
            break
        fi
    done
    [ ! -f $makef ] && return 0

    # رسیدگی به ‎Makefile‎های پیوست شده.
    makef_inc=$( grep -E '^-?include' $makef |
                 sed -e "s,^.* ,"$makef_dir"/," )
    for file in $makef_inc; do
        [ -f $file ] && makef="$makef $file"
    done


    # اگر دارای یک پاره کلمه برای تکمیل هستیم، محدود
    #+           نمودن تکمیل‌ها به انطباق‌های آن کلمه.
    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]}

    #    به دست آوردن لیستی از پردازش‌ها
    #+   (ارزیابی نخست sed به پردازش‌های
    #+تولید شده توجه می‌کند، ارزیابی دوم
    #+  متوجه کسب نام اصلی پردازش است).
    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

# متغیرهای محلی:
# mode:shell-script
# sh-shell:bash
# پایان:

و این هم یک پاره کد از فایل ‎.bash_profile‎ آموزنده ‎Andrzej Szelachowski‎.

مثال ‎M-2‎. فایل ‎.bash_profile‎

#   از فایل ‎~/.bash_profile‎ تنظیم  ‎Andrzej Szelachowski‎:

# توجه کنید که اگر یک متغیر بخواهد export بشود، ممکن است
#+                 به طرز برخورد ویژه‌ای نیاز داشته باشد.

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 \`"

# برای اینکه جایگزینی فرمان به طور لفظی به یک متغیر تخصیص
#+ داده شود، از escapeها و نقل‌قول‌های دوگانه استفاده کنید:
#+       PCT="\` ... \`"  . . .
#در غیر اینصورت، مقدار متغیر ‎PCT‎ فقط یکبار، وقتی متغیر از
#+ فایل ‎.bash_profile‎ صادر و خوانده شود، تخصیص داده می‌شود
#+ و پس از آن حتی اگر ‎ID‎ کاربر عوض شود، تغییر نخواهد کرد.

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

#       متغیری را که مقدارش تغییر می‌کند ‎Escape‎ کنید:
#        if [[ \$EUID -eq 0 ]],
# وگرنه مقدار متغیر ‎EUID‎ فقط یکبار تخصیص داده می‌شود،
#+                                        مانند بالا.

# وقتی متغیری تخصیص داده می‌شود، باید به صورت escape شده احضار شود:
#+       echo \$T,
#وگرنه مقدار متغیر ‎T‎ از لحظه export و خوانده شدن متغیر PCT از فایل
#+ ‎.bash_profile‎ گرفته می‌شود. بنابراین، در این مثال تهی خواهد بود.

#    وقتی مقدار متغیر شامل یک سمی‌کالن باشد، باید نقل‌قولی قوی بشود،
# به این صورت:  ‎T='$LIGHTRED'‎  در غیر اینصورت، سمی‌کالن به عنوان یک
#                                   جداکننده فرمان تفسیر خواهد شد.

#    متغیرهای ‎PCT‎ و ‎PS1‎ می‌توانند در یک متغیر جدید ‎PS1‎ ادغام بشوند:

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'\`"

# شگرد آن استفاده از نقل‌قول‌های قوی برای بخش‌های متغیر قدیمی ‎PS1‎ است