#!/bin/bash # setcd bash functions: interpret this in your current shell by sourcing it # ------------------------------------------------------------------------------ function chdir () { # a bare-bones cd: does nothing paticular command cd "$@" } # ------------------------------------------------------------------------------ function cd_basic () { local oldCWD=`pwd` local newCWD=`command cd "$@" > /dev/null && pwd` if [[ "$oldCWD" == "$newCWD" ]]; then return 0 # destination is already current directory fi if [[ -z "$newCWD" ]]; then return 1 # failed to change to destination directory fi # execute leaving script if any if [[ -r "$oldCWD/.bashcd_old" ]]; then source "$oldCWD/.bashcd_old" fi # change directory command pushd "$@" > /dev/null # execute entering script if any if [[ -r "$newCWD/.bashcd" ]]; then source "$newCWD/.bashcd" fi } # ------------------------------------------------------------------------------ function cd () { # cd should accept: # "-" revert to previous directory (popd) # path push path onto the dirs stack, go there # path:path:path n use n to index the path list; cd there # path path path n use n to index the path list; cd there # path1 path2 path3 go to path1 # n go to $DIRSTACK[n] if n is not a directory # cd will also source the following files if it can change directory: # old pwd's .bashcd_old - before changing directories # new pwd's .bashcd - after changing directories if [[ -z "$setcdProc" ]]; then setcd fi local argc=$# local -a argv=( "$@" ) local last local num local dir if [[ $argc -gt 0 ]]; then last=${argv[argc - 1]} else last= fi if [[ $argc -eq 0 ]]; then # default directory - go home set -- ~ elif [[ $argc -eq 1 ]]; then case "$last" in -) popcd return $? ;; [0-9]*) num=`echo "$last" | sed -e 's/[^0-9]//g'` if [[ "$num" == "$last" ]]; then # completely numeric if [[ -d $num || "$CDPATH" == *:${num}:* ]]; then dir="$num" echo dir="$num" elif [[ "$num" -lt ${#DIRSTACK[*]} && "$num" -ge 0 ]]; then dir=`command dirs -l -p | awk "NR==$num + 1 "'{ print $0 }'` # dir=`echo ${DIRSTACK[num]}` # doesn't work if dir contains '~' # echo num=$num "DIRSTACK[$num]"="${DIRSTACK[num]}" dir="$dir" else echo "${0}: ${FUNCNAME}: directory stack index out of range" 1>&2 return 1 fi set -- "$dir" else # leave alone : fi ;; *) ;; esac else # [[ $argc -gt 1 ]]; then num=`echo "$last" | sed -e 's/[^0-9]//g'` if [[ "$num" == "$last" ]]; then unset argv[$argc-1] dir=$( IFS=: echo "${argv[*]}" | awk -F: '{i='"$num"' + 1; if (NF >= i) print $i }' ) if [[ -n "$dir" ]]; then set -- $dir fi else set -- "$1" fi fi cd_basic "$@" } # ------------------------------------------------------------------------------ function lcd () { command dirs -l -v } # ------------------------------------------------------------------------------ function popcd_basic () { local oldCWD=`pwd` local newCWD=`pwd` local -a stack=( `dirs -l` ) local depth=${#DIRSTACK[*]} local i case "x$1" in x+*) command popd "$1" > /dev/null ; return $? ;; x-*) command popd "$1" > /dev/null ; return $? ;; x[0-9]*) i=$((0 + $1)) ;; x*) i=0 ;; esac [[ $i -ge $depth ]] && i=$depth [[ $i -le 0 ]] && i=1 newCWD="${stack[$(( (i > 0) ? i : 0 ))]}" while [[ ( ! -d "$newCWD" ) && ( $i -lt $depth ) ]]; do echo "$i - directory $newCWD does not exist: dropping" 1>&2 i=$((i + 1)) newCWD="${stack[$i]}" done if [[ $i == $depth ]]; then newCWD=~ fi if [[ "$oldCWD" != "$newCWD" ]]; then # execute leaving script if any if [[ -r "$oldCWD/.bashcd_old" ]]; then source "$oldCWD/.bashcd_old" fi fi if [[ $i == $depth ]]; then # echo "$1 - beyond depth ${depth}: clearing stack" 1>&2 dirs -c command pushd ~ -n > /dev/null command popd +1 > /dev/null else # get rid of the intermediate levels while [[ $i -gt 1 ]]; do command popd +0 -n > /dev/null i=$((i - 1)) done fi # change directory command popd > /dev/null # execute entering script if any if [[ -r "$newCWD/.bashcd" ]]; then source "$newCWD/.bashcd" fi } # ------------------------------------------------------------------------------ function popcd () { # popcd should accept # +n calls popd +n (removing the nth entry) # -n calls popd -n (removing the (depth - n)th entry) # n pops the stack until n etries have been removed popcd_basic "$@" } # ------------------------------------------------------------------------------ function - () { popcd "$@" } # ------------------------------------------------------------------------------ function _ () { popcd "$@" } # ------------------------------------------------------------------------------ function setcd_usage () { local u='call setcd as follows: setcd [-nuUtThixXfb][-c|-C ] -n: add node host name to prompt (N: only for xterm title) -u: add user name to prompt -U: add user name to xterm title -t: add terminal name to prompt -T: add terminal name to xterm title -h: add history number to prompt -c: shorten the path if too long - equivalent to -C4 -C: shorten the path if too long - if is > 0: max len = columns / else show last - path elements -i: apply C shortening for icon (else last part of path) -x: use n, u options and display directory in xterm titles -X: display directory in xterm icons -f: add n, u values to end of directory in xterm icons -b: add n, u values to start of directory in xterm icons' echo "$u" 1>&2 } # ------------------------------------------------------------------------------ function setcd () { if [[ -z "$setcdProc" ]]; then setcdProc=$$ export cdDepth=$((cdDepth + 1)) [[ $cdDepth -gt 1 ]] && export cdDepthS="<`basename ${SHELL}`:$cdDepth>" fi # see setcd_usage for usage local onode='' oXnode='' local ouser='' oXuser='' local oterm='' oXterm='' local ohist='' ocutN=0 oXcut='' local oXnu='' oXdir='' oXnupos='' OPTIND=1 if [[ ( $# -gt 0 ) && ( x"$1" != x-* ) ]]; then local arg1="$1" shift set -- "-$arg1" "$@" fi while getopts nNuUtThcC:iIxXfb arg; do case $arg in n) onode=y ;; N) oXnode=y ;; u) ouser=y ;; U) oXuser=y ;; t) oterm=y ;; T) oXterm=y ;; h) ohist=y ;; c) ocutN=4 ;; C) if ( echo "$OPTARG" | grep -q -E -e '^-?[0-9]+$' ) || \ [ "$OPTARG" -eq 0 ]; then ocutN=$OPTARG else echo "${0}: setcd: bad divisor number for -C option:"\ "$OPTARG" 1>&2 setcd_usage return 1 fi ;; i | I) oXcut=y ;; x) oXnu=y ;; X) oXdir=y ;; D) oXdir= ;; f) oXnupos=f ;; b) oXnupos=b ;; \? | :) setcd_usage return 1 ;; esac done shift `expr $OPTIND - 1` OPTIND=1 if [[ $# -gt 0 ]]; then echo "${0}: setcd: does not take non-option arguments" 1>&2 setcd_usage return 1 fi # set up prompt local prefix= suffix= cutcmd= [[ -n "$onode" ]] && prefix="`tput bold; tput smso; hostname`:" # [[ -n "$ouser" ]] && prefix="`tput bold; tput smso; whoami`@$prefix" [[ -n "$ouser" ]] && prefix="`tput bold; tput smso; `\u@$prefix" [[ -n "$oterm" ]] && prefix="`tput bold`[`tty | sed -e s./dev/..`]$prefix" # [[ -n "$oterm" ]] && prefix="`tput bold`\][\l]\[$prefix" [[ -n "$ohist" ]] && prefix="\]!\!!\[$prefix" prefix="`tput bold; tput smso`$cdDepthS`tput sgr0`$prefix" prefix="\[$prefix`tput sgr0; tput rev`\]" suffix="\[`tput sgr0`\]" if [[ -n "$ocutN" && "$ocutN" -ne 0 ]]; then if [[ "$ocutN" -lt 0 ]]; then cutcmd='CWDL=$((0 - '"$ocutN"')); if [[ ( ${#CWD} -gt $CWDL ) && ( $CWDL > 0 ) ]]; then CWDP="..."; CWD=${CWD:${#CWD}-${CWDL}}; else CWDP=""; fi;' else # $ocutN -gt 0 cutcmd='CWDL=$((('"$ocutN"' > 0) ? (COLUMNS / '"$ocutN"') : 0)); if [[ ( ${#CWD} -gt $CWDL ) && ( $CWDL > 0 ) ]]; then CWDP="..."; CWD=${CWD:${#CWD}-${CWDL}}; else CWDP=""; fi;' fi fi # set up prompt command string PROMPT_COMMAND='CWD=`pwd`; CWDP=''; '"$cutcmd"' PS1="'"$prefix"'$CWDP$CWD'"$suffix"' "' } # ------------------------------------------------------------------------------ function addcd () { # call addcd as follows: # addcd # this adds as a "nickname" of the current directory path : } # ------------------------------------------------------------------------------ function autoaddcd () { : } # ------------------------------------------------------------------------------ function remcd () { : } # ------------------------------------------------------------------------------ function resetcd () { : }