# Rod's .bashrc file (Rod Moffitt rod@rod.info) # $Id: bashrc 13240 2011-12-09 06:07:42Z rmoffitt $ # Copyright (C) Rod Moffitt + others # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # if not running interactively, don't do anything [ -z "$PS1" ] && return # source the system bashrc if one exists if [ -e "/etc/bash.bashrc" ]; then . /etc/bash.bashrc fi # automatic setting of $DISPLAY (if not set already) # this works for linux - your mileage may vary... function get_xserver { case $TERM in xterm ) XSERVER=$(who am i | awk '{print $NF}' | tr -d ')''(' ) 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 ulimit -S -c 0 # don't want any coredumps set -o notify #set -o noclobber # to prevent direction deleting files #set -o xtrace # useful for debuging #set -o nounset # useful for debuging # enable options shopt -s cdspell shopt -s checkhash shopt -s checkwinsize shopt -s sourcepath shopt -s no_empty_cmd_completion # bash >= 2.04 only shopt -s cmdhist shopt -s histappend histreedit histverify shopt -s extglob # necessary for programmable completion # disable options shopt -u mailwarn unset MAILCHECK # disable shell warning of incoming mail export TIMEFORMAT=$'\nreal %3R\tuser %3U\tsys %3S\tpcpu %P\n' export HISTIGNORE="&:bg:fg:h" export HISTSIZE=10000 export HISTTIMEFORMAT="%F %H:%M:%S " export HOSTFILE=~/.hosts # put a list of remote hosts in ~/.hosts # color definitions red='\e[0;31m' RED='\e[1;31m' green='\e[0;32m' GREEN='\e[1;32m' blue='\e[0;34m' BLUE='\e[1;34m' cyan='\e[0;36m' CYAN='\e[1;36m' yellow='\e[0;33m' YELLOW='\e[1;33m' NC='\e[0m' # no color function xtitle { echo -en "\033]0;$*\007" } # 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 pattern in a set of files and highlight them function fstr { OPTIND=1 local case="" local usage="fstr: find string in files. Usage: fstr [-i] \"pattern\" [\"filename pattern\"] " 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 } # cut last n lines in file, 10 by default function cuttail { nlines=${2:-10} sed -n -e :a -e "1,${nlines}!{P;N;D;};N;ba" $1 } # crops off the end of stdin to the specified size when a +ve argument, # otherwise crops off the specified size from the start of a stdin for a # -ve argument, size is in bytes unless a sufix of k/K (kilobytes 1000), # m/M (megabytes 1000000), g/H (gigabytes 1000000000) is found - Rod function crop { local len=$1 local bs=1 case "$len" in *k|*K|"* k"|"* K") bs=1000 ;; *m|*M|"* m"|"* M") bs=1000000 ;; *g|*G|"* g"|"* G") bs=1000000000 ;; *) ;; esac len=$(echo $len | sed -e "s#[a-zA-Z]*##g") if [ $len -le 0 ]; then len=$(echo $len | sed -e "s#\-##g") dd bs=$bs skip=$len 2> /dev/null else dd bs=$bs count=$len 2> /dev/null fi } # crop a file without having to make an intermediate temp file - Rod function filecrop { local TMPFILE=tmp.$$ cat "$1" | crop "$2" > $TMPFILE mv -f $TMPFILE "$1" } # du will bork if presented with a very large number of files via the command # line, fdu gets around this by using find to gather the list of files, the first # parameter is the directory (. if omitted), any other parameters are passed to du function fdu { local where=. local opt= if [ "$#" -ge 1 ]; then where=$1 shift if [ "$#" -ge 1 ]; then opt=$* fi fi find $where -type f -exec du $opt \{\} \; } # clean up source files by: 1) fromdos'ing 2) removing excess white-space # 3) converting tabs to 3 space - Rod function cleansrc { local fromdos=`which fromdos 2> /dev/null` if [ -z "$fromdos" ]; then echo "can't find fromdos" else for filename; do local TMPFILE=tmp.$$ $fromdos < "$filename" | sed -e "s/\s*$//g;s/\t/ /g" > $TMPFILE mv -f $TMPFILE "$filename" done fi } # lowercase and change spaces and extraneous dots to underscores in filenames - Rod # - put '-num' before the name to optionally remove leading '999_' numbers # - put '-count' before the name to optionally prefix the files with an increasing index function lowercase { local mv=`which mv 2> /dev/null` if [ -z "$mv" ]; then echo "can't find mv" else local nonum=""; local count=""; for filename; do case "$filename" in "-num" ) nonum="yes";; "-count" ) count=1;; * ) if [ ! -e "$filename" ]; then echo "lowercase: $filename doesn't exist" else local dir=$(dirname "$filename") if [ $dir == "." ]; then dir="" else dir="$dir/" fi local nf=$(basename "$filename" | tr A-Z a-z | \ tr '[:cntrl:]\\\177-\377,:;()\-\[\]!@#\$%\^\?\*~{}=]' ' ' | \ sed -e 's/"//g' | sed -e "s/'//g" | sed -e 's/`//g' | sed -e s#\&#and#g | \ sed -e 's/[[:space:]]/_/g;s/_\+/_/g;s/^_//;s/_$//;s/\_\./\./g;s/\.\_/\_/g') local gotdots=$(echo $nf | grep "\.\." -) while [ "$gotdots" != "" ]; do nf=$(echo $nf | sed -e 's/\.\./\./g') gotdots=$(echo $nf | grep "\.\." -) done if [ ! -d "$filename" ]; then local last=$nf gotdots=$(echo $nf | grep "\." -) while [ "$gotdots" != "" ]; do last=$nf nf=$(echo $nf | sed -e 's/\./_/') gotdots=$(echo $nf | grep "\." -) done nf=$last else nf=$(echo $nf | sed -e 's/\./_/g') fi if [ -n "$nonum" ]; then nf=$(echo $nf | sed -e 's#^[0-9]*_##g') fi if [ -n "$count" ]; then nf=$(printf "%03d_$nf" $count) count=$(($count + 1)) fi local newname="${dir}${nf}" if [ "$filename" != "$newname" ]; then $mv -i -- "$filename" "$newname" echo "lowercase: $filename --> $newname" else echo "lowercase: $filename not changed" fi fi ;; esac done fi } # rename files with random names with 32 character file names, preserving the # file extension - Rod function randrename { local mv=`which mv 2> /dev/null` if [ -z "$mv" ]; then echo "can't find mv" else for filename; do if [ ! -e "$filename" ]; then echo "randrename: $filename doesn't exist" else local dir=$(dirname "$filename") if [ $dir == "." ]; then dir="" else dir="$dir/" fi local nf=$(basename "$filename") local last=$nf local gotdots=$(echo $nf | grep "\." -) while [ "$gotdots" != "" ]; do last=$nf nf=$(echo $nf | sed -e 's/\./_/') gotdots=$(echo $nf | grep "\." -) done last=$(echo $last | sed 's/[^\.]*//') local randname=$(randpw 32 | tr A-Z a-z) local newname="${dir}${randname}${last}" if [ "$filename" != "$newname" ]; then $mv -i -- "$filename" "$newname" echo "randrename: $filename --> $newname" else echo "randrename: $filename not changed" fi fi done fi } # updates the link to a file - Rod function relink { if [ "$#" -lt 2 ] then echo "usage: relink { ... }" elif [ ! -d "$1" ] then echo "directory '$1' doesn't exist" else local dir=$1 shift for filename; do local link=$(find $dir -name $filename) if [ -n "$link" ] then ln -sf "$link" echo "relink: linking $link" else echo "relink: failed to find $file" fi done fi } # renames a file adding the resolution to the end - Rod function renameres { local identify=`which identify 2> /dev/null` local mv=`which mv 2> /dev/null` if [ "$#" -lt 1 ] then echo "usage: renameres { ... }" elif [ -z "$identify" ]; then echo "can't find identify (apt-get install imagemagick)" elif [ -z "$mv" ]; then echo "can't find mv" else for filename; do if [ ! -e "$filename" ]; then echo "renameres: $filename doesn't exist" else local res=$($identify -ping -format "%wx%h" "$filename") if [ -z $res ] then echo failed to determine resolution of "$filename" else local filebase=${filename%.*} local ext=$((${#filename}-${#filebase})) ext=${filename: -$ext} res=$(echo "$filebase" | sed "s/$/_${res}$ext/") $mv -i -- "$filename" "$res" echo "renameres: $filename --> $res" fi fi done fi } # finds a free loop device and uses it - Rod function flosetup { if [ "$#" -lt 1 ]; then echo "missing file" return -1 fi local losetup=`which losetup 2> /dev/null` local lobase='/dev/loop'; local loopidx=0 local lofile=$1 if [ -z "$losetup" ]; then echo "can't find losetup" return -1 fi if [ ! -f "$lofile" ]; then echo "invalid file" return -1 fi while true do local lodev=$lobase/$loopidx; if [ ! -b $lodev ]; then echo "failed to find free loop device" return -1 fi $losetup $lodev $lofile 2> /dev/null if [ $? -eq 0 ]; then echo "$lodev" return 0 fi loopidx=$((loopidx+1)) done } # detaches a loop device based on the mount - Rod function closetup { if [ "$#" -lt 1 ] then echo "missing mount" return -1 fi local losetup=`which losetup 2> /dev/null` local lomount=$1 if [ -z "$losetup" ]; then echo "can't find losetup" return -1 fi loopdev=`$losetup -a 2> /dev/null | grep $lomount | sed s/:.*//g` if [ -n "$loopdev" ]; then $losetup -d $loopdev 2> /dev/null else return -1 fi } # simple dump of alphanumeric characters, useful for mouse picking # passwords when it isn't safe to use the keyboard - Rod function chars { letters='abcdefghijklmnopqrstuvwxyz' letters=$letters$(echo $letters | tr 'a-z' 'A-Z') echo ${letters}0123456789 } # find all files under the current directory which grep the specified id3 # information, example 'id3find Trainspotting *' - Rod function id3find { local string=$1 shift local tempfile=/tmp/.id3find.$$ for file in $@ do id3info $file > $tempfile 2> /dev/null test=$(grep -i "$string" $tempfile) if [ -n "$test" ]; then echo $file; fi done rm -f $tempfile } # swap 2 filenames around function swap { 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:-".*"} ; } # get current host related info function ii { echo -e "\n${RED}You are logged on ${YELLOW}$HOSTNAME$NC as ${GREEN}$USER" echo -e "\n${RED}Additionnal information:$NC "; uname -a echo -e "\n${RED}Users logged on:$NC "; w -h echo -e "\n${RED}Current date:$NC "; date echo -e "\n${RED}Machine stats:$NC "; uptime echo -e "\n${RED}Memory stats:$NC "; free echo } # repeat n times command function repeat { local i max max=$1 shift for ((i=1; i <= max ; i++)); do eval "$@" done } # ask for confirmation function ask { echo -n "$@" '[y/n] ' read ans case "$ans" in y*|Y*) return 0 ;; *) return 1 ;; esac } # cool little function to prevent 'rm * .txt' when you meant 'rm *.txt', # tcsh beats bash in only this feature, now bash has it as well! - Rod function rmstar { set +f # re-enable globbing local oldargs="$@" # search for a '*' until [ -z "$1" ] do if [ "$1" == "*" ] then ask "Do you really want to delete all files?" if [ "$?" -eq 1 ] then return fi fi shift done local rm=`which rm 2> /dev/null` $rm $oldargs } # need to temporarily disable globbing to allow re-running of 'rm' with the # string asis, the only down side is that if this alis is run in the background # then set +f won't be set until the command completes - Rod alias rm="IFS='^'; set -f; rmstar" # clean up a path, removing excess forward slashes - Rod function cleanpath { echo $1 | sed -e "s#//*#/#g" -e 's#/$##g' -e 's#/:#:#g' } # nice routine to manage paths, first argument is the command: # to either "insert" it at the beginning, "append" it to the end, # "remove" the entry, all operating with the second argumemt, or # any other command string to show the current path - Rod function path { dir=$(cleanpath "$2") PATH=$(cleanpath "$PATH" | sed -e "s/^/:/" -e "s/$/:/" \ -e "s#:$dir:#:#g" -e "s/^://" -e "s/:$//") case "$1" in i* ) PATH=$2:$PATH ;; a* ) PATH=$PATH:$2 ;; r* ) ;; * ) echo -e ${PATH//:/\\n} ;; esac } # echo text taken from stdin using the color specified as the argument # which must be listed under 'color definitions' above - Rod function color { eval col=\$$1 echo -ne $col cat /dev/stdin echo -ne "$NC" } # outputs data in colon-separated hex format - Rod function bin2hex { local hexdump=`which hexdump 2> /dev/null` if [ -z "$hexdump" ]; then echo "can't find hexdump" else $hexdump -ve '1/1 "%02x:"' | sed s#:\$#\\n# fi } # outputs data in hex format, optionally limits length to # specified number of hex chars - Rod function bin2nhex { local hexdump=`which hexdump 2> /dev/null` if [ -z "$hexdump" ]; then echo "can't find hexdump" else local data=$($hexdump -ve '1/1 "%02x"' | sed s#\$#\\n#) if [ "$#" -eq 1 ]; then data=$(echo $data | head -c $1) fi echo $data fi } # outputs data in C friendly char array hex format - Rod function bin2chex { local hexdump=`which hexdump 2> /dev/null` if [ -z "$hexdump" ]; then echo "can't find hexdump" else bin2hex | sed -e "s#^#const unsigned char myarray\[\] = { 0x#;s#:#, 0x#g;s#\$# };#" fi } # for every file under a directory create a single line with # an MD5 hash and the file name converted so it can be # sorted and easily compared no matter what system it is on function md5dir { local md5deep=`which md5deep 2> /dev/null` if [ -z "$md5deep" ] then echo "can't find md5deep" elif [ $# -ne 1 ]; then echo "usage: md5dir " else $md5deep -lr ${1} | sed s#${1}## | tr -d [:punct:][:blank:] | sort -df fi } # uses md5dir to provide a single hash of a directory function md5dirsum { local md5deep=`which md5deep 2> /dev/null` if [ -z "$md5deep" ] then echo "can't find md5deep" elif [ $# -ne 1 ]; then echo "usage: md5dirsum " else md5dir "${1}" | $md5deep | sed "s#-#${1}#" fi } # get a random number, between 0 and the argument-1 - Rod function rand { local base64=`which base64 2> /dev/null` if [ $# -lt 1 ]; then echo "usage: rand " elif [ ! -r "/dev/urandom" ] || [ -z "$base64" ]; then echo "can't read /dev/urandom and/or find base64" elif [ $1 -gt 0 ]; then # get some real entropy RANDOM=$(head -c 20 /dev/urandom | $base64 \ | sed -e "s#[^0-9]*##g" | tail -c 5) # because of integer rounding larger numbers cause overflow on results echo $(($RANDOM/(32768/$1))) else echo "invalid ceiling value" fi } # select randomly from a argument - Rod function randlist { if [ $# -gt 0 ]; then local index=$(rand $#) shift $index echo $1 fi } # outputs a specific amount of random data - Rod function randdata { if [ $# -lt 1 ]; then echo "how much random data?" elif [ $1 -gt 0 ]; then head -c $1 /dev/urandom else echo "invalid length" fi } # removes repeating characters from a string - Rod function charuniq { local i local str=$1 local len=$(echo -n $str | wc -c) for ((i=1; i < $(($len/2+2)); i++)); do str=$(echo "$str" | sed 's/\(.\)\1/\1/g') done echo "$str" } # outputs a random password by piping /dev/urandom into base64, since not all # password based systems allow non-alphanumerics they are filtered out, takes # a single parameter which is the number of characters - Rod function randpw { local base64=`which base64 2> /dev/null` if [ $# -lt 1 ]; then echo "what length?" elif [ -z "$base64" ]; then echo "can't find base64" elif [ $1 -gt 0 ]; then local testlen=0 local outlen=$1 local pw="" while [ $testlen -lt $outlen ]; do local in=$(head -c $((outlen*5/6+1)) /dev/urandom | $base64) pw=$(echo "$pw$in" | tr -cd 'A-Za-z0-9') pw=$(charuniq "$pw") testlen=$(echo -n $pw | wc -c) done pw=$(echo "$pw" | head -c $outlen) echo "$pw" else echo "invalid length" fi } # generate a random 16 bit integer, good for selecting random ports - Rod function randport { val=$(randdata 32 | bin2nhex 4) echo $((0x$val)) } # randomly moves out files to specified directory from current directory # until specified size is met - Rod function randpurge { if [ "$#" -lt 2 ]; then echo "randpurge: " return; fi local mv=`which mv 2> /dev/null` if [ -n "$mv" ]; then local len=$1 local destdir=$2 local bs=1 case "$len" in *k|*K|"* k"|"* K") bs=1000 ;; *m|*M|"* m"|"* M") bs=1000000 ;; *g|*G|"* g"|"* G") bs=1000000000 ;; *) ;; esac bslen=$(echo $len | sed -e "s#[a-zA-Z]*##g") size=$(du --block-size=$bs -s | sed -e "s#\.##g") if [ $bslen -le $size ]; then files=$(find . | grep -v ^\.$) file2mv=$(randlist $files) if [ -n "$file2mv" ]; then echo "moving $file2mv to $destdir" $mv -i "$file2mv" "$destdir" randpurge "$len" "$destdir" fi fi fi } # run a command for a specified time (value is any time value supported by # sleep) - Rod function runfor { if [ "$#" -lt 2 ]; then echo "runfor: