# ----------------------------------------------------------------------------- # Stephen Niedzielski # This file is sourced by .bash_profile at bash launch. # ----------------------------------------------------------------------------- # Safety Options # Fail if undefined variables are used. set -u # Status of pipeline is last non-zero status of command or rightmost command # status. set -o pipefail # Prohibit redirection overwriting >. set -C # ----------------------------------------------------------------------------- # Print # http://wiki.archlinux.org/index.php/Color_Bash_Prompt colorless='\e[0m' red='\e[1;31m' yellow='\e[1;33m' green='\e[1;32m' alias e=echo print_ng() { echo -e ${red}ng:${colorless} "$@" >&2; } print_wn() { echo -e ${yellow}wn:${colorless} "$@" >&2; } print_ok() { echo -e ${green}ok:${colorless} "$@" ; } # ----------------------------------------------------------------------------- # Version Determination CYG_1_7_5=0 DAR_10_3_0=0 case "`uname -sr`" in CYGWIN_NT-*\ 1.7.5\(0.225/5/3\)) CYG_1_7_5=1 ;; 'Darwin 10.3.0') DAR_10_3_0=1 ;; *) print_ng 'unknown terminal' ;; esac # ----------------------------------------------------------------------------- # Common Shell Aliases alias mv='mv -i' alias m=mv alias cp='cp -i' alias rm='rm -i' alias r=rm alias md=mkdir alias se=set alias mktmp=mktemp alias h=history if [ $CYG_1_7_5 -eq 1 ] then alias l='ls -A1p --color=always --group-directories-first' # Alphabetically. elif [ $DAR_10_3_0 -eq 1 ] then alias l='ls -A1pG' # Alphabetically. fi alias lex='l -X' # By extension. alias lsi='l -S' # By size. alias lct='l -c' # By creation time. alias lmt='l -t' # By modification time. alias lat='l -u' # By access time. if [ $CYG_1_7_5 -eq 1 ] then alias tree='cmd tree' elif [ $DAR_10_3_0 -eq 1 ] then true #alias tree='d -T' fi # ----------------------------------------------------------------------------- # Pipe # Generate script for detecting existence of stdin pipe. [ ! -e ~/scripts/is_pipe.sh ] && \ rm -f ~/scripts/is_pipe.sh && \ echo 'readlink /proc/$$/fd/0|egrep -v ^/dev/console$ > /dev/null' > ~/scripts/is_pipe.sh alias is_pipe='~/scripts/is_pipe.sh' alias ip=is_pipe # ----------------------------------------------------------------------------- # Miscellaneous # xargs newline delimited. alias x="xargs -d '\n'" # Bastard son of find; newline delimited. alias f='find -O3 . -nowarn -depth -regextype egrep' a() { [ $1 -gt 0 ]; } # args na() { [ $1 -eq 0 ]; } # no args ipoa() { ip || test $1 -gt 0; } # Is pipe or argument(s). ipana() { ip && [ $1 -eq 0 ]; } # Is pipe and no arguments. np() { ! ip; } npana() { np && na $1; } # no pipe and no args alias timestamp='date +%F-%H-%M-%S' if [ $CYG_1_7_5 -eq 1 ] then alias cls='cmd cls' # Clear screen. #alias bell='! sndrec32 /play "C:\Windows\Media\ding.wav"' # /close alias bell='"$PROGRAMFILES"/Windows\ Media\ Player/wmplayer "c:\\Windows\\Media\\ding.wav"' fi alias path="echo \$PATH|sed 's_:_\n_g'" # Print each path on a newline. alias pdftotext='pdftotext -layout' alias str='strings -a' alias s='sed -r' dic() { ! wn "$@" -over; } # Dictionary definition. alias doxygen='cmd doxygen' t() { if ip then d2u|x touch "$@" < /dev/fd/0 else touch "$@" fi } # Doesn't handle embedded comments like const char * foo = "choo /* choo */". strip_c_cmt() { ipana $# && \ python -c 'import re, sys; sys.stdout.write(re.sub("/\*(.|\r?\n)*?\*/", "", sys.stdin.read(), 0))' } exp() { "$WINDIR/explorer" "`cygpath -w "${1:-.}"`"& } notepad() { "$WINDIR/notepad" ${1:+"`cygpath -w "$1"`"}& } tag() # Index workspace. { npana || return 1 f > f.txt && \ egrep '\.(c|cpp|h|hpp)$' f.txt > fxchpp.txt && \ ctags - < fxchpp.txt bell } beep_off() { # TODO: I think this only works in cygwin for backspace and tab bells. bind 'set bell-style none' net stop beep sc config beep start= disabled } cb() # Clipboard. { na $# || return 1 if ip then putclip else getclip fi } # These look strange because they're evaluated once by the shell and once by # sed. alias esc="s 's_(\\\\| )_\\\\\\1_g'" alias escex="s 's_[^a-zA-Z0-9]_\\\\\\0_g'" # ----------------------------------------------------------------------------- # grep alias g='egrep --color=always' alias gd='aspell dump master|g -i' # grep dictionary xg() { d2u|x egrep --color=always "$@"; } # xargs newline delimited grep alias gp='pls|ntip 2|g -i' # grep process # ----------------------------------------------------------------------------- # Head / Tail # One screen worth. alias ead='head -n $LINES' alias ail='tail -n $LINES' alias tip='head -n 1' ntip() { tail -n +"$@"; } # All from tip offset. alias base='tail -n 1' nbase() { head -n +"$@"; } # All to base offset. # ----------------------------------------------------------------------------- # Filename Manipulation cy() { if ip then cygpath "$@" -f - else if a $# && [ "${1:0:1}" != '-' -o $# -gt 1 ] then cygpath "$@" else cygpath "$@" "$PWD" fi fi } alias cyw='cy -w' # Windows. alias cyu='cy -u' # UNIX. alias cym='cy -m' # Mixed. bn() # Basename. { if ipana $# then d2u|x -n 1 basename < /dev/fd/0 else basename "$@" fi } dn() # Dirname. { if ipana $# then d2u|x -n 1 dirname < /dev/fd/0 else dirname "$@" fi } # ----------------------------------------------------------------------------- # Processes alias kill='kill -f' alias pls='ps -asW' # Process grep and kill. pk() { gp --color=none "$@"|s 's_[ \t]+([0-9]+).*_\1_'|x kill -f; } alias jobs='jobs -l' # ----------------------------------------------------------------------------- # gVim if [ $CYG_1_7_5 -eq 1 ] then alias gvim="/c/Program\ Files*/Vim/vim72/gvim.exe" fi alias vanilla_gvim='gvim -U NONE' # for visitors v() { gvim -p "$@"& } # ----------------------------------------------------------------------------- # File Type Detection # These functions *guess*. Return matching inputs. is_txt() { if ipana $# then file -N0 --mime-encoding -f - else file -N0 --mime-encoding "$@"|grep -av binary|s 's_\x0 .*__' fi } is_bin() { if ipana $# then file -N0 --mime-encoding -f - else file -N0 --mime-encoding "$@"|grep -a binary|s 's_\x0 binary$__' fi } # ----------------------------------------------------------------------------- # Last.fm # API documentation available at http://www.last.fm/api. # $1 Last.fm API method. # ... Optional method parameters. fm() { local method="$1" shift # Append '-d' to specify URL encoding is necessary. There's probably a better # way to do this. local params= local i=0 while [ $# -gt 0 ] do params[i]="-d$1" let i+=1 shift done curl \ -d 'api_key=fede83da81dbe5c79f0f056286a0c379' \ -d "method=$method" \ ${params:+"${params[@]}"} \ 'http://ws.audioscrobbler.com/2.0/' } alias fmsn="sed -nr 's_^ (.*)_\1_p'" # $1 Artist. # $2 Number of similar artists returned (optional). fm_sim_art() { fm artist.getSimilar "artist=$1" ${2:+"limit=$2"} } #cat *|sort|uniq -dc|sort -r # ----------------------------------------------------------------------------- # cmd if [ $CYG_1_7_5 -eq 1 ] then cmd() { # This looks like a bit of a hack, but in general parents propagate their # environment to their children, whether it's Popen in Python or # CreateProcess in Win32. I think this is the proper way to do it -- get it # from the registry. I could use env here, but the prompt seems to expect # environment variables to be fully expanded. # Some programs require this, like p4. local pwd="$(cygpath -w "$PWD")" # Restore path to system default. local path="$(cat '/proc/registry/HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Session Manager/Environment/Path')" && \ "$SYSTEMROOT/system32/cmd" /S /E:ON /F:ON /V:ON /C 'set PWD='"$pwd"'& set PATH='"$path"'&' "$@" } alias cmd_win='cmd start cmd' alias cyg_win='cmd_win /c "`cyw /`\\cygwin.bat"' fi # CYG_1_7_5 # ----------------------------------------------------------------------------- # p4 # Wrapping p4 like this let's let's us pipe to and from the clipboard easily # at this layer and all higher level wrappers. p4() { if ip then cmd p4 -x - "$@" else cmd p4 "$@" fi } alias p4win='cmd start p4win' # winners don't use drugs, they use p4win alias p4w=p4win alias p4v='cmd start p4v' # TODO: Some or all of these are busted with the new P4. Try fstat in this # version but see if can maintain backward compatibility. # Will not work if # is used within filenames. alias p4sd="s 's_^(\.\.\. )?(//[^#]+).*_\2_'" alias p4sv="s 's_^(\.\.\. )?//[^#]+#([0-9]+).*_\2_'" alias p4sdv="s 's_^(\.\.\. )?(//[^#]+#[0-9]+).*_\2_'" alias p4sl="s 's_^//[^#]+#[0-9]+ - ([a-z]+ )?(.+)_\2_'" alias p4scl="s 's_Change ([0-9]+) on [0-9]{4}/[0-9]{2}/[0-9]{2} by .*_\1_'" # TODO: integrate / fix. # Requires dominant cs to new location. p4replace() { p4 revert -k "$@" && \ p4 sync -k "$@" && \ p4 edit "$@" } # Accepts labels and files from stdin. Prints tip revs for outdated files. p4tip() { ipana $# && p4sd|p4 files|p4sd|p4 sync -n 2>/0 } # Accepts labels and file revs from stdin. prints changelist delta between have # and specified. p4dcl() { ! ipana $# && return 1 local chgs=`mktmp` local stdin=`mktmp` cat >> $stdin p4 files|s 's_^(\.\.\. )?(//[^#]+).*_\2#head_' < $stdin|p4 changes|sort -u >> $chgs && \ p4sd < $stdin|p4 have|p4sdv|p4 changes >> $chgs && \ sort $chgs|uniq -u rm -f $chgs $stdin } # ----------------------------------------------------------------------------- # Find Files with Extension # (Newline delimited.) # $1 opt iregex for file ext # $2, ... opt args passed to find fx() { local rex= if [ $# -gt 0 ] then rex="($1)" shift fi f -type f -iregex '^.*'"${rex}"'$' ${@:+"$@"} } alias fxc="fx '\.c'" alias fxh="fx '\.h'" alias fxch="fx '\.c|\.h'" alias fxcpp="fx '\.c|\.cpp'" alias fxhpp="fx '\.h|\.hpp'" alias fxchpp="fx '\.c|\.cpp|\.h|\.hpp'" # ----------------------------------------------------------------------------- # Jump # If no arguments specified, pushd. # Else if $1 specified and is a dir, pushd dir. # Else treat $1 as an iregex describing a portion of the PWD. If result of # iregex is a dir, pushd dir, else error. j() { if [ $# -eq 0 ] then P return fi if [ -d "$1" ] then P "$1" return fi # Ideally use nuls or newlines. e foo|s $'s\1oo\1aa\1' works but # e foo|s $'s\0oo\0aa\0' does not. local d="`cym "$PWD"|s -n "s"$'\r'"(.*(^|:|/)$1[^/:]*($|\:|/)).*"$'\r'"\1"$'\r'"ip"`" if [ $? -eq 0 ] && [ -n "$d" ] then P "$d" return fi return 1 } J() { P ${@:++"$@"}; } alias dirs='dirs -v' p() { popd "$@" > /0 && dirs; } P() { pushd "$@" > /0 && dirs; } alias b='cd ..' alias b1='b' alias b2='b1;b' alias b3='b2;b' alias b4='b3;b' alias b5='b4;b' alias c=cd # ----------------------------------------------------------------------------- # Bash History # Append to history instead of overwriting. shopt -s histappend # Save history regardless of number of terminals. # TODO: confirm this works... export SAVEHIST=1 export HISTSIZE=10000 # Ignore duplicate lines so we don't have to keep tapping up. export HISTIGNORE='&' # Convert multi-line commands to single line in history. shopt -s cmdhist # ----------------------------------------------------------------------------- # Miscellaneous # Specify a Python configuration file. export PYTHONSTARTUP=~/.pythonrc # Some programs use this to determine what shell to use. export SHELL win_title=Cygwin # Adjust window size after each command as appropriate. shopt -s checkwinsize # Extended globbing. See features at http://www.caliban.org/bash/. shopt -s extglob # Return files beginning with . in path-name expansion. shopt -s dotglob # Prompt. # Change to: # $PWD # : # With adjustable title. # Note: colors here must be between \[\033[ and \] if [ $CYG_1_7_5 -eq 1 ] then PS1='\[\033]0;${win_title}\007\]\n\[\033[\e[0;32m\]`e=$?;cygpath -am "$PWD";if [ $e -eq 0 ];then echo -e \[\033[\e[0m\];else echo -e "\[\033[\e[1;31m\]";fi`: \[\033[\e[0m\]' elif [ $DAR_10_3_0 -eq 1 ] then PS1='\[\033]0;${win_title}\007\]\n\[\033[\e[0;32m\]$PWD\n`if [ $? -eq 0 ];then echo -e \[\033[\e[0m\];else echo -e "\[\033[\e[1;31m\]";fi`: \[\033[\e[0m\]' fi # Not quite sure what these do. They seem to change the CL interface a bit. set editing-mode vi set -o vi # ----------------------------------------------------------------------------- # Links if [ ! -e /0 ] then rm -f /0 ln -s /dev/null /0 fi if [ $CYG_1_7_5 -eq 1 ] then if [ ! -e ~/desktop ] then # Either symbolic link is broken or non-existent. # Hose the link if it exists. rm -f ~/desktop # Make a new link. ln -s /cygdrive/c/Documents\ and\ Settings/"`whoami`"/Desktop ~/desktop fi if [ ! -e /c ] then rm -f /c ln -s /cygdrive/c /c fi if [ ! -e /cb ] then rm -f /cb ln -s /dev/clipboard /cb fi elif [ $DAR_10_3_0 -eq 1 ] then if [ ! -e /dat ] then ln -s /Volumes/DAT/sn /dat fi fi tmp_derar_dir() { for i in *.rar *.zip do # unrar x -ad -- "$i" . > /0 && unrar e -ad -- "$i" > /0 && \ mv "$i" "$i".bk done } # ----------------------------------------------------------------------------- # Notes # echo|dd bs=110M conv=sync of=110MB.bin - gen big fat file # objdump, dumpbin #nodosfilewarning # is_bin also returns dirs, sym links, & other non-reg files, which normally # isn't what i want. NOTE: this will return Windows links #is_binf() #{ # # newline is delimter # local IFS=$'\n' # local rv='' # for f in `is_bin "$@"` # #is_bin "$@"|while read -r f # do # if [ -f "$f" ] # then # # HACK: escape backslashes, then delimit with a newline. under limited # # testing, this is slightly faster than echoing each match to stdout # # direct # rv+="${f//\\/\\\\}\n" # #echo "$f" # fi # done # if [ -n "$rv" ] # then # echo -en "$rv" # fi #} #g '\' # find word foo # find duplicates - sort|uniq -d # 2>&1 stderr to stdout # &> stderr and stdout to file # net config server /hidden:yes # paste, join, cut # reverse list: tac # cp ../M8660SRFXXXWSA0037_0/{clientspec_updates.cs,core_wiredconnectivity_depends.plf,properties.ini} . # {1..10} --> 1 2 3 4 5 6 7 8 9 10