#!/bin/bash # # # # -- UTF-8 -- # if tty -s; then interactive_shell=1; fi [ "$interactive_shell" ] && echo "Running .bash_include" [ "$interactive_shell" ] && default_tty_setting=`stty -g` # Internal Variables colorprompting='\[\e[1;31m\]\!\[\e[m\] [\[\e[1;33m\]\u\[\e[m\]@\[\e[1;32m\]\h\[\e[m\] \[\e[1;36m\]\w\[\e[m\]]\$ ' nocolorprompting='\! [\u@\h \w]\$ ' historycountfile="$HOME/.bash_history.count" historybackupfile="$HOME/.bash_history.bak" bgrunfiledir="$HOME/tmp/bgrun-`whoami`" trashdir="$HOME/trash" HISTSIZE=1000000 HISTFILESIZE=1000000 HISTCONTROL=ignoredups:ignorespace REALPATH_PROGRAM="realpath" CFLAGS="-Wall -pipe -g" # Environment Variables export EDITOR=vim export FCEDIT=vim export PAGER=less # Aliases alias startcolor='PS1=$colorprompting' alias stopcolor='PS1=$nocolorprompting' alias ll='ls -l' alias grep='grep --color=always' alias rm='rm -i' alias cp='cp -pi' alias mv='mv -i' alias jobs='jobs -l' alias less='less -RS' alias cccc='LANG=C;LC_ALL=C' alias enus='LANG=en_US.UTF-8;LC_ALL=en_US.UTF-8' alias big5='LANG=zh_TW.Big5;LC_ALL=zh_TW.Big5' alias zhtw='LANG=zh_TW.UTF-8;LC_ALL=zh_TW.UTF-8' alias utf8='LANG=zh_TW.UTF-8;LC_ALL=zh_TW.UTF-8' alias savetty='default_tty_setting=`stty -g`' alias resetty='stty $default_tty_setting' # Functions function compile_all () { local noask=0 [ "$1" = '' ] && echo "Which file(s) do you want to compile? " && return 1 [ "$1" = "-n" ] && noask=1 if [ "$noask" = "0" ]; then read -e -p "CFLAGS: " -i "$CFLAGS" NEWCFLAGS read -e -p "LDFLAGS: " -i "$LDFLAGS" NEWLDFLAGS [ "$NEWCFLAGS" '!=' '' ] && CFLAGS=$NEWCFLAGS [ "$NEWLDFLAGS" '!=' '' ] && LDFLAGS=$NEWLDFLAGS else shift fi while [ "$1" '!=' '' ] do local TARGETFILE="`echo "$1" | cut -d . -f 1`" local SUFFIX="`echo "$1" | cut -d . -f 2`" if [ -f "$1" ]; then true else printf\ "\e[1;33mWarning\e[0m: $1 Non-existent file or not a regular file\n" shift ; continue fi [ "$TARGETFILE" = "$1" ] && shift && continue if [ "$SUFFIX" = "c" ]; then echo "[CC] $1 -> $TARGETFILE" gcc $CFLAGS "$1" $LDFLAGS -o "$TARGETFILE" elif [ "$SUFFIX" = "cpp" ]; then echo "[CXX] $1 -> $TARGETFILE" g++ $CFLAGS "$1" $LDFLAGS -o "$TARGETFILE" else printf "$1: Unknown suffix (\e[1;33mskipped\e[0m)\n" fi [ "$?" '!=' "0" ] && printf\ '\e[1;31mError\e[0m while compiling file\n' shift done return 0 } function convert_to_html () { while [ "$1" '!=' '' ] do for i in "$1" do vim $i -c 'set background=dark' \ -c 'highlight PreProc ctermfg=darkcyan' \ -c "$BEFORE_CONVERT_TO_HTML" \ -c "$BEFORE_CONVERT_TO_HTML1" \ -c "$BEFORE_CONVERT_TO_HTML2" \ -c TOhtml \ -c :w \ -c :qa done shift done } function mkscreenacl () { PERMIT_COMMAND="select windowlist other meta detach reset hardcopy info redisplay lastmsg next prev xon xoff windows suspend help colon copy paste writebuf readbuf displays stuff attach" while [ "$1" '!=' '' ] do for i in $PERMIT_COMMAND do echo "aclchg $1 +x $i" done echo "aclchg $1 -rw \"#?\"" shift done } ########## Background ########## alias bgr=bgrun alias bgv=bgview alias bgl=bglist alias bgc=bgcount alias bgls=bglist alias bgrm=bgclean function bgrun () { [ "$#" = "0" ] && return 1 [ '!' -d "$bgrunfiledir" ] && mkdir -p "$bgrunfiledir" local current_time=`date "+%Y%m%d-%H%M%S"` local cmdname=`echo "$1" | sed -e 's/-/_/g' -e 's/\\//_/g' -e 's/ /_/g'` if [ "`echo "$cmdname" | cut -c 1`" == "_" ] then cmdname=`echo "$cmdname" | cut -c 2-` fi local filename="$bgrunfiledir/$current_time-$cmdname" echo "Writing to $filename" echo "$@" > $filename "$@" &>> "$filename" & } function bglist () { local viewtime=0 [ "$1" = "--full" ] && viewtime=1 { for i in `find "$bgrunfiledir" -maxdepth 1 -mindepth 1 | sort` do [ "$viewtime" == "1" ] && echo "$i" head -n 1 "$i" done } | { if [ "$viewtime" == "1" ] then local readstat=0 local -i i=1 while true do local dateandtime_long local cmdline read dateandtime_long read cmdline [ "$?" '!=' "0" ] && break local dateandtime=`basename "$dateandtime_long"` #### local part_year=`echo $dateandtime | cut -c 1-4` #### local part_month=`echo $dateandtime | cut -c 5-6` #### local part_date=`echo $dateandtime | cut -c 7-8` #### local part_hour=`echo $dateandtime | cut -c 10-11` #### local part_minute=`echo $dateandtime | cut -c 12-13` #### local part_second=`echo $dateandtime | cut -c 14-15` echo "$dateandtime" | { read -n 4 part_year read -n 2 part_month read -n 2 part_date read -n 1 drop_this_char; unset drop_this_char read -n 2 part_hour read -n 2 part_minute read -n 2 part_second printf '%6d' "$i" echo " $part_year-$part_month-$part_date $part_hour:$part_minute:$part_second $cmdline" } i=$i+1 done else cat -n fi } | $PAGER } function bgview () { local -i yourchoice if [ "$1" = "" ] then yourchoice=`bgcount` else if [ "$1" -le "0" ] then yourchoice=$((`bgcount`+$1)) else yourchoice=$1 fi fi echo "Your choice is $yourchoice." local realfilename=`find "$bgrunfiledir" -maxdepth 1 -mindepth 1 | sort | sed -n ${yourchoice}p` echo "Command Line: `head -n 1 "$realfilename"`" read -e -p "View '$realfilename' ? " confirm if [ "$confirm" = "n" ] || [ "$confirm" = "N" ] then return 1 fi { printf "Command Line: " cat "$realfilename" } | $PAGER } function bgcount () { find "$bgrunfiledir" -maxdepth 1 -mindepth 1 | cut -d - -f 2,3 | wc | awk '{print $2}' } function bgclean () { if [ "$1" = "all" ] then echo "Removing the directory $bgrunfiledir" rm -rf "$bgrunfiledir" & return 0 else split_arguments "$@" local -i i=0 while [ "${arglist[$i]}" ] do arglist[$i]="-e ${arglist[$i]}p" i=$i+1 done local oneline find "$bgrunfiledir" -maxdepth 1 -mindepth 1 | sort | sed -n ${arglist[*]} | { while read oneline do echo "Removing $oneline" rm -f "$oneline" done } fi unset arglist unset prefixlist } function bgdu () { du -a "$bgrunfiledir" } ########## Background End ########## function check_dmesg () { [ "$#" = "0" ] && return 1 while true do PREVIOS_DMESG_BUF="$DMESG_BUF" DMESG_BUF="`dmesg`" [ "$PREVIOS_DMESG_BUF" '!=' "$DMESG_BUF" ] && [ "$FIRST_RUN" = "0" ] && echo '===> You should check the system message buffer <===' sleep $1 [ "$?" '!=' "0" ] && return 1 FIRST_RUN=0 done } function prehistory_backup () { echo "Checking current history file" local currentcount=`wc "$HISTFILE" | awk '{print $1}'` [ '!' -f "$historycountfile" ] && touch "$historycountfile" local -i previoushistorycount previoushistorycount=`cat "$historycountfile"` if [ "$currentcount" -lt "$previoushistorycount" ] then printf "\e[1;31mWarning\e[m: Your $HISTFILE may be TRUNCATED OR OVERWRITTEN BY OTHER PROGRAMS!\n" printf "Note: \e[1;33m$currentcount\e[m < $previoushistorycount\n" echo "Your $historycountfile and $historybackupfile will not be overwritten until this problem is fixed." echo " 1. Check your $HISTFILE." echo " 2. Edit your $HISTFILE manually if some unexpected changes are found." echo " (You may need $historybackupfile to do it) " echo " 3. Remove the file $historycountfile." echo " 4. Run the command \`prehistory_backup' again." return 3 fi echo -n "Backing up current history file ($previoushistorycount -> $currentcount, " if [ "$previoushistorycount" = "$currentcount" ] then echo "no modification)" else echo "+$(($currentcount-$previoushistorycount)))" fi echo "$currentcount" > "$historycountfile" \cp -f "$HISTFILE" "$historybackupfile" } ########## Trash Manager ########## alias trash_put=trash_mv function trash_mv () { [ "$#" = "0" ] && return 1 [ '!' -d "$trashdir" ] && mkdir -p "$trashdir" local original_path local current_time local -i i=0 split_arguments "$@" while [ "${arglist[$i]}" ] do original_path="`$REALPATH_PROGRAM "${arglist[$i]}"`" current_time=`date "+%Y%m%d-%H%M%S"` better_time=`date "+%Y-%m-%d %H:%M:%S"` dirname="`basename "${arglist[$i]}" | sed -e 's/-/_/g' -e 's/ /_/g'`" fulldirname="$trashdir/$current_time-$dirname" mkdir -p "$fulldirname" echo "Move: ${arglist[$i]} -> $fulldirname" "${prefixlist[@]}" mv "${arglist[$i]}" "$fulldirname" echo "$better_time" > "$fulldirname/information.date" echo "$original_path" > "$fulldirname/information.path" i=$i+1 shift done unset arglist unset prefixlist } function trash_rm () { echo bb } function trash_ls () { echo cc } function trash_cd () { echo dd } function trash_recover () { echo yy } function trash_count () { echo zz } function trash_du () { split_arguments "$@" local oneline find "$trashdir" -maxdepth 1 -mindepth 1 | sort | { while read oneline do echo "'$oneline'" done } | xargs -n 10 "${prefixlist[@]}" du -s unset arglist unset prefixlist } ########## Trash Manager End ########## ########## Help ########## alias helpf='help_function' alias helpm='help_myself' function print_iconv () { [ "$1" = "$2" ] && cat && return 0 iconv -f "$1" -t "$2" } function help_function () { [ "$#" = "0" ] && { cat << ENDHELPMSG <<< Help >>> help_myself [arguments ...] help_function [functions ...] <<< Group: Background >>> bgrun command [arguments ...] bglist [--full] bgview [number] bgclean [all | numbers ...] bgcount bgdu <<< Group: Trash >>> trash_mv [filename ...] [-- sudo_prefix ...] trash_ls trash_cd [number] trash_recover [number] [-- sudo_prefix ...] trash_rm [all | numbers ...] [-- sudo_prefix ...] trash_count trash_du [-- sudo_prefix ...] <<< Group: PATH Editor >>> path_editor ldpath_editor x split_path x split_path_core x update_path x path_editor_core <<< Other >>> compile_all [-n] filename ... convert_to_html filename ... mkscreenacl username ... check_dmesg seconds prehistory_backup check_important_files backup_file filename ... [-- sudo_prefix ] keep_sudo_credential [seconds] x split_arguments [arguments ...] ENDHELPMSG } && return 0 local current_charset=`echo "$LC_ALL" | cut -d . -f 2` local -i i while [ "$1" ] do case "$1" in "help_myself") cat << ENDHELPMSG | print_iconv "UTF-8" "$current_charset" help_myself 一個測試命令列的小函式 ENDHELPMSG ;; "help_function") cat << ENDHELPMSG | print_iconv "UTF-8" "$current_charset" help_function 顯示 .bash_include 提供的額外函式清單 註:前方加上「x」符號者表示此為內部使用的函式,不宜直接使用 ENDHELPMSG ;; "bgrun") cat << ENDHELPMSG | print_iconv "UTF-8" "$current_charset" bgrun command [arguments ...] 執行指令 command 並將輸出導入檔案 註:此函式會自動以目前時間和指令名稱為檔案命名 ENDHELPMSG ;; "bglist") cat << ENDHELPMSG | print_iconv "UTF-8" "$current_charset" bglist [--full] 列出所有使用 bgrun 執行的指令 若加上 --full 選項,則可同時察看時間 ENDHELPMSG ;; "bgview") cat << ENDHELPMSG | print_iconv "UTF-8" "$current_charset" bgview [number] 顯示以 bgrun 執行指令的輸出,若省略 number,表示是最近一次執行的指令 若 number > 0, 表示第 number 個指令 (此數值可由 bglist 函式取得) 若 number <= 0, 表示第「指令總數-number」個指令 (指令總數可由 bgcount 函式取得) ENDHELPMSG ;; "bgclean") cat << ENDHELPMSG | print_iconv "UTF-8" "$current_charset" bgclean [all | numbers ...] bgclean all 可清除所有指令的輸出檔 bgclean 3 5 7 10 表示清除第 3、5、7、10 個指令輸出檔 (編號可由 bglist 取得) ENDHELPMSG ;; "bgcount") cat << ENDHELPMSG | print_iconv "UTF-8" "$current_charset" bgcount 顯示指令輸出檔總數 ENDHELPMSG ;; "bgdu") cat << ENDHELPMSG | print_iconv "UTF-8" "$current_charset" bgdu 顯示每個指令輸出檔的檔案大小 (單位:KB) ENDHELPMSG ;; *) echo "Help message for $1 is not found" ;; esac shift done } function help_myself () { echo "argc = $#" echo "argv[0] = $0" i=1 while [ "$1" ] do echo "argv[$i] = $1" i=$(($i+1)) shift done } ########## Help End ########## function split_arguments () { local argcount=$# local -i i=0 local prefix_start=0 while [ "$1" ] do if [ "$prefix_start" == "0" ] then if [ "$1" = "--" ] then prefix_start=1 i=0 shift continue else arglist[$i]="$1" fi else prefixlist[$i]="$1" fi i=$i+1 shift done } function check_important_files () { IMPORTANT_FILES="$HOME/.screenrc $HOME/.vimrc" for i in $IMPORTANT_FILES do [ '!' -f "$i" ] && printf "\e[1;31mWarning\e[m: \e[1;33m$i\e[m does not exist.\n" done } ########## PATH Editor ########## function split_path_core () { echo "$current_path" | { while read -d : oneline do [ '!' "$oneline" = '^' ] && echo "$oneline" done [ '!' "$oneline" = '^' ] && echo "$oneline" } unset oneline } function split_path () { coproc split_path_core readarray -t -u ${COPROC[0]} patharr wait $COPROC_PID } function update_path () { current_path='' local -i i=0 local firsttime="yes" while [ "${patharr[$i]}" ] do if [ '!' "${patharr[$i]}" = "^" ] then if [ "$firsttime" ] then firsttime='' else current_path+=':' fi current_path+="${patharr[$i]}" fi i=$i+1 done } function path_editor () { path_editor_core } function ldpath_editor () { path_editor_core ld } function path_editor_core () { if [ "$1" = "ld" ] then export current_path="$LD_LIBRARY_PATH" else export current_path="$PATH" fi local should_continue="yes" local command local command_sub local command_sub2 local -i i while [ "$should_continue" ] do split_path i=0 echo "========================================" while [ "${patharr[$i]}" ] do echo "$i: ${patharr[$i]}" i=$i+1 done [ "$i" = '0' ] && echo "(Empty or not declared)" echo "========================================" read -e -p "[A]ppend/(D)elete/(E)dit/(M)ove/(R)eset/(Q)uit ? " command case "$command" in ''|A|a) read -e -p "Type new entry: " patharr[$i] update_path ;; D|d) read -e -p "Index: " command_sub patharr[$command_sub]='^' update_path ;; E|e) read -e -p "Index: " command_sub read -e -p "Modify this entry: " -i "${patharr[$command_sub]}" patharr[$command_sub] update_path ;; M|m) read -e -p "From: " command_sub read -e -p "To: " command_sub2 swaptmp="${patharr[$command_sub]}" patharr[$command_sub]="${patharr[$command_sub2]}" patharr[$command_sub2]="$swaptmp" unset swaptmp update_path ;; R|r) if [ "$1" = "ld" ] then current_path="$LD_LIBRARY_PATH" else current_path="$PATH" fi current_path="$PATH" ;; Q|q) if [ "$1" = "ld" ] then export LD_LIBRARY_PATH="$current_path" echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" else export PATH="$current_path" echo "PATH=$PATH" fi should_continue='' ;; *) echo " *** Unknown command *** " ;; esac done unset patharr unset current_path } ########## PATH Editor End ########## function backup_file () { split_arguments "$@" local current_time=`date +%Y%m%d` local rootfilename local -i i=0 local -i j while [ "${arglist[$i]}" ] do if [ '!' -f "${arglist[$i]}" ] then printf "\e[1;31mError\e[m: ${arglist[$i]} does not exist or it is not a regular file.\n" i=$i+1 continue fi rootfilename="${arglist[$i]}.$current_time" if [ -e "$rootfilename" ] then j=0 while [ "$j" -lt "10" ] do if [ -e "$rootfilename.$j" ] then j=$j+1 continue else "${prefixlist[@]}" \cp -p "${arglist[$i]}" "$rootfilename.$j" "${prefixlist[@]}" touch -r "${arglist[$i]}" "$rootfilename.$j" break fi done if [ '!' "$j" -lt "10" ] then printf "\e[1;31mError\e[m: Can not create a backup file for ${arglist[$i]}.\n" printf "\e[1;33mPlease delete some backup file because I only use 0 - 9.\e[m\n" fi else "${prefixlist[@]}" \cp -p "${arglist[$i]}" "$rootfilename" "${prefixlist[@]}" touch -r "${arglist[$i]}" "$rootfilename" fi i=$i+1 done unset arglist unset prefixlist } function keep_sudo_credential () { if [ "$1" ] then update_sudo_interval="$1" else update_sudo_interval="60" fi while true do sudo -v sleep "$update_sudo_interval" done } # Doing something umask 0022 if [ "$interactive_shell" ] then echo "Running interactive shell configuration" check_important_files startcolor prehistory_backup bind '"\e[A":history-search-backward' bind '"\e[B":history-search-forward' fi if [ "`uname`" = "Linux" ] then [ "$interactive_shell" ] && echo "Setting special things for Linux" REALPATH_PROGRAM="readlink -f" ulimit -c unlimited fi [ "$interactive_shell" ] && echo "Setting shell options" shopt -s histappend shopt -s checkwinsize shopt -s checkjobs shopt -s checkhash shopt -s cmdhist shopt -s mailwarn [ "$interactive_shell" ] && echo "Done"