====== Functions ====== ===== Extending commands/builtins ===== ==== Extended cd #0 ==== (cd path/path/file), go to the directory containing the file, no questions asked added support for cd foo bar to change from /foo/subdir to /bar/subdir (not friendly to reiserfs4's files as directories). function cd () { if [[ -z $2 ]]; then if [[ -f $1 ]]; then builtin cd $1:h else builtin cd $1 fi else if [[ -z $3 ]]; then builtin cd $1 $2 else echo cd: too many arguments fi fi } ==== Extended cd #1 ==== When given two arguments, substitute ALL occurences of the first argument in $PWD by the second argument (the builtin cd replaces just the first occurence). If given a non-directory argument, test if its "dirname" is a directory and change to it. cd () { emulate -LR zsh if [[ $# -ge 3 ]]; then echo cd: too many arguments >&2 return 1 elif [[ $# -eq 2 ]]; then ## builtin cd $1 $2 local newdir=${(S)PWD//$1/$2} echo $newdir builtin cd $newdir elif [[ $# -eq 1 ]]; then if [[ ! -d $1 && -d $1:h ]]; then echo $1:h builtin cd $1:h else builtin cd $1 fi else builtin cd fi } ==== Extended cd #2 ==== This version does: * cd /etc/fstab -> cd /etc * corrections on the given dirname (if directory could not be found) * all(?) other possible invocations of the builtin 'cd' function smart_cd () { if [[ -f $1 ]] ; then [[ ! -e ${1:h} ]] && return 1 print correcting ${1} to ${1:h} builtin cd ${1:h} else builtin cd ${1} fi } function cd () { setopt localoptions setopt extendedglob local approx1 ; approx1=() local approx2 ; approx2=() if (( ${#*} == 0 )) || [[ ${1} = [+-]* ]] ; then builtin cd "$@" elif (( ${#*} == 1 )) ; then approx1=( (#a1)${1}(N) ) approx2=( (#a2)${1}(N) ) if [[ -e ${1} ]] ; then smart_cd ${1} elif [[ ${#approx1} -eq 1 ]] ; then print correcting ${1} to ${approx1[1]} smart_cd ${approx1[1]} elif [[ ${#approx2} -eq 1 ]] ; then print correcting ${1} to ${approx2[1]} smart_cd ${approx2[1]} else print couldn\'t correct ${1} fi elif (( ${#*} == 2 )) ; then builtin cd $1 $2 else print cd: too many arguments fi } ==== hgrep ==== grep like function which highlights matches.\\ note that newer grep can do this, possibly more accurately, with the --color flag. # hgrep - highlight grep if (( ! $# )); then echo "Usage: $0:t [-e pattern...] [file...]" >&2 return 1 fi local -a regex local htext=`echotc so` ntext=`echotc se` while [[ "$1" = -e ]]; do regex=( $regex "$2" ) shift 2 done if (( ! $#regex )); then regex=( "$1" ) shift fi regex=( "-e s/${^regex[@]}/$htext&$ntext/g" ) sed ${(Ff)regex[@]} "$@" ===== Distribution-specific ===== ==== Debian/OSX local/remote upgrade ==== ############################## ### by sandor szuecs Dec 2006 ### ### upgrades local or remote: osx, debian or ubuntu systems ### usage local: $ upgrade ### usage remote: $ upgrade $HOST ############################## upgrade () { if [ ! $1 ] ; then print "local upgrade" if [ `uname` = "Darwin" ]; then print "osx_upgrade_local" osx_upgrade_local elif [ `uname -o` = "GNU/Linux" ]; then print "debian_upgrade_local" debian_upgrade_local else print "I don't know what can I do for this type of machine" fi elif [[ $1 = "help" || $1 = "--help" || $1 = "-h" ]] ; then print "local usage for upgrading Mac OS X or debian systems including fink and darwin ports: upgrade and clean" print 'remote usage: upgrade $debian_server' elif [ $1 ]; then print "remote upgrade" if [[ `ssh $1 uname -o 2&>/dev/null` = "GNU/Linux" ]] ; then print "debian_upgrade_remote" debian_upgrade_remote $1 elif [[ `ssh $1 uname 2&>/dev/null` = "Darwin" ]] ; then print "osx_upgrade_remote" osx_upgrade_remote $1 else print "$1 is not a debian nor an osx machine" print "please implement an upgrade function for this kind of machine!" fi fi } # osx local upgrade osx_upgrade_local () { print "=== update Mac systems ===" sudo softwareupdate -i -a #if [ -x /usr/bin/gem ] ; then # sudo /usr/bin/gem update #fi if [ -x /sw/bin/fink ] ; then print "=== fink upgrade ===" sudo fink selfupdate sudo fink update-all sudo fink cleanup fi if [ -x /opt/local/bin/port ] ; then print "=== darwin ports ===" #sudo port sync sudo port -d selfupdate #sudo port -uR upgrade installed sudo port -ucRvpt upgrade installed sudo port clean --all installed if [ -x /opt/local/bin/gem ] ; then sudo /opt/local/bin/gem update fi fi if [ -d /Library/Application\ Support/TextMate/Bundles ]; then pushd /Library/Application\ Support/TextMate/Bundles svn up *.tmbundle popd osascript -e 'tell app "TextMate" to reload bundles' fi } # local debian upgrade debian_upgrade_local (){ print "Upgrading Debian" sudo apt-get update && sudo apt-get -u upgrade print "Cleaning up" sudo apt-get clean } # remote osx upgrade osx_upgrade_remote (){ if [ ! $1 ]; then print "usage: osx_upgrade_remote $osx_server" print "Perhaps you want osx_upgrade_local ?" else # local variables declaration local OSX_UP local FINK_UP local DARWINPORTS_UP # ask before the upgrade until [[ $OSX_UP == 'y' || $OSX_UP == 'n' ]]; do print -n "Process osx upgrade on $1 (y/n)?" read -q OSX_UP done; until [[ $FINK_UP == 'y' || $FINK_UP == 'n' ]]; do print -n "Process fink upgrade on $1 (y/n)?" read -q FINK_UP done; until [[ $DARWINPORTS_UP == 'y' || $DARWINPORTS_UP == 'n' ]]; do print -n "Process darwinports upgrade on $1 (y/n)?" read -q DARWINPORTS_UP done; # upgrade if answer is y if [[ $OSX_UP == "y" ]] ; then print "=== update Mac systems ===" ssh $1 -t /usr/bin/sudo /usr/sbin/softwareupdate -i -a fi if [[ $FINK_UP == "y" ]] ; then print "=== fink upgrade ===" ssh $1 -t /usr/bin/sudo /sw/bin/fink selfupdate ssh $1 -t /usr/bin/sudo /sw/bin/fink update-all ssh $1 -t /usr/bin/sudo /sw/bin/fink cleanup fi if [[ $DARWINPORTS_UP == "y" ]] ; then print "=== darwin ports ===" ssh $1 -t /usr/bin/sudo /opt/local/bin/port selfupdate #ssh $1 -t /usr/bin/sudo /opt/local/bin/port -uR upgrade installed ssh $1 -t /usr/bin/sudo /opt/local/bin/port upgrade installed ssh $1 -t /usr/bin/sudo /opt/local/bin/port clean --all installed fi fi } # remote debian upgrade debian_upgrade_remote (){ if [ ! $1 ]; then print "usage: debian_upgrade_remote $debian_server" print "Perhaps you want debian_upgrade_local ?" else print "remote debian upgrade on $1" ssh $1 -t sudo apt-get update # print what should be upgraded ssh $1 -t "sudo apt-get -s upgrade" # ask before the upgrade local dummy print -n "Process the upgrade y/n ?" read -q dummy if [[ $dummy == "y" ]] ; then ssh $1 -t "sudo apt-get -u upgrade --yes && sudo apt-get clean" print "upgrade on $1 done" fi fi } ==== Debian upgrade ==== # if the first argument is void, proceed local upgrade # else, send command via ssh # assume user have sufficient permission for upgrade # without interaction # # Note: # i use sudo with the follow lines # # Cmnd_Alias DEBIAN = /usr/bin/apt-get, /usr/bin/dpkg # asyd ALL = PASSWD: ALL, NOPASSWD: DEBIAN upgrade () { if [ -z $1 ] ; then sudo apt-get update sudo apt-get -u upgrade else ssh $1 -t sudo apt-get update # ask before the upgrade local dummy ssh $1 -t sudo apt-get --no-act upgrade echo -n "Process the upgrade ?" read -q dummy if [[ $dummy == "y" ]] ; then ssh $1 -t sudo apt-get -u upgrade --yes fi fi } compdef _hosts upgrade ===== Standalone ===== ==== Quick rename ==== function name() { [[ $#@ -eq 1 ]] || { echo Give exactly one argument ; return 1 } test -e "$1" || { echo No such file or directory: "$1" ; return 1 } local newname=$1 if vared -c -p 'rename to: ' newname && [[ -n $newname && $newname != $1 ]] then command mv -i -- $1 $newname else echo Some error occured; return 1 fi } ==== scpzshconf ==== Copy your zsh conf to another host. # scpzshconf # (c) Julien Danjou <julien@jdanjou.org> # License: GPLv2 function scpzshconf { if [ ! -z $1 ]; then echo -n "Sending zsh conf to $1... " cd $HOME && \ tar cf - .zsh/rc/* \ .zshrc 2> /dev/null | \ ssh $1 "tar xf - 2> /dev/null" && \ cd $OLDPWD && echo done fi } ==== Functions for use with the e glob flag ==== e.g. ls *(e:'in ~':) in() { [[ -e $1/$REPLY ]] } empty() { a=( $REPLY/*(N[1]) ); (( ! $#a )) } fattr() { local val=${${${(s.=.)$(getfattr -n user.$1 $REPLY 2>/dev/null)}[2]%\"}#\"} [[ -z $val ]] && return 1 [[ -z $2 ]] && return 0 [[ $val = $~2 ]] } empty() allows you to find empty directories. You still need the / though. e.g: zstyle ':completion:*:rmdir:*' file-patterns "*(/l2e.empty.):empty-dirs" '*(/):directories' Note that zsh 4.2 has a builtin glob qualifer (F) to do this. fattr() gives access to filesystem extended attributes (if you use XFS or, with Linux 2.6, ext3). ==== Functions to display values of environment variables ==== Examples: ''ev disp'' shows the values of env variables whose names start with "disp" (case insensitive), such as DISPLAY. ''eva lib'' does the same but "lib" can be in the middle of the name. ev() { echo set | egrep -i \^$1 |sed -e 's/=/ /' -e '/^PATH/d' -e '/^CDPATH/d' | sort echo } eva() { echo set | egrep -i "^[a-z_]*$1" |sed -e 's/=/ /' -e '/^PATH/d' -e '/^CDPATH/d' | sort echo } Some version of egrep complains because there are non-printable characters from the output of "set" (try "set | egrep e" to see if the output is only "binary file matches"). Then you may have to add an option of -a to egrep. ==== Create personal .fpath dir and zcp and zln links ==== Author: Copyright (c) 2005 Eric P. Mangold - teratorn (-at-) gmail (-dot) com License: MIT. http://www.opensource.org/licenses/mit-license.html # nice to have your own fpath dir [[ ! -d ~/.fpath ]] && mkdir ~/.fpath fpath=(~/.fpath $fpath) # zln and zcp have to be symlinks to the zmv function for name in zln zcp; do fn=~/.fpath/$name # this is a hack to see if it is a broken symlink # these symlinks will break when you upgrade your zsh if [ -L $fn -a ! -e $fn ]; then rm $fn fi if [[ ! -a $fn ]]; then for dir in $fpath; do if [[ -a $dir/zmv ]]; then ln -s $dir/zmv $fn break fi done fi done ==== browse a file or path (open in web browser) ==== Author: Copyright (c) 2005 Eric P. Mangold - teratorn (-at-) gmail (-dot) com License: MIT. http://www.opensource.org/licenses/mit-license.html You may need to change this to suite your browser of choice. If anyone wants to generalize this, that would be cool. browse () { if [[ $BROWSER == opera ]]; then opera -remote "openURL(file://`pwd`/$1,new-page)" else $BROWSER file://"`pwd`/$1" fi } alias br=browse ==== smart python ==== Author: Copyright (c) 2005 Eric P. Mangold - teratorn (-at-) gmail (-dot) com License: MIT. http://www.opensource.org/licenses/mit-license.html # Prefer ipython for interactive shell smart_python () { # this function is actually rather dumb if [[ -n $1 ]]; then python $argv else #if no parameters were given, then assume we want an ipython shell if [[ -n $commands[ipython] ]]; then ipython else python fi fi } alias py=smart_python # tab-complete options for smart_python just like for python compdef _python smart_python ==== smart sudo ==== Author: Copyright (c) 2005 Eric P. Mangold - teratorn (-at-) gmail (-dot) com License: MIT. http://www.opensource.org/licenses/mit-license.html # Give us a root shell, or run the command with sudo. # Expands command aliases first (cool!) smart_sudo () { if [[ -n $1 ]]; then #test if the first parameter is a alias if [[ -n $aliases[$1] ]]; then #if so, substitute the real command sudo ${=aliases[$1]} $argv[2,-1] else #else just run sudo as is sudo $argv fi else #if no parameters were given, then assume we want a root shell sudo -s fi } alias s=smart_sudo compdef _sudo smart_sudo Or using an alias' property: smart_sudo () { if [[ -n $1 ]]; then sudo $argv else #if no parameters were given, then assume we want a root shell sudo -s fi } # the trailing space causes the next word to be checked for alias expansion alias s='smart_sudo ' compdef _sudo smart_sudo ==== extract any archive ==== Author: Copyright (c) 2005 Eric P. Mangold - teratorn (-at-) gmail (-dot) com License: MIT. http://www.opensource.org/licenses/mit-license.html extract_archive () { local old_dirs current_dirs lower lower=${(L)1} old_dirs=( *(N/) ) if [[ $lower == *.tar.gz || $lower == *.tgz ]]; then tar zxfv $1 elif [[ $lower == *.gz ]]; then gunzip $1 elif [[ $lower == *.tar.bz2 || $lower == *.tbz ]]; then bunzip2 -c $1 | tar xfv - elif [[ $lower == *.bz2 ]]; then bunzip2 $1 elif [[ $lower == *.zip ]]; then unzip $1 elif [[ $lower == *.rar ]]; then unrar e $1 elif [[ $lower == *.tar ]]; then tar xfv $1 elif [[ $lower == *.lha ]]; then lha e $1 else print "Unknown archive type: $1" return 1 fi # Change in to the newly created directory, and # list the directory contents, if there is one. current_dirs=( *(N/) ) for i in {1..${#current_dirs}}; do if [[ $current_dirs[$i] != $old_dirs[$i] ]]; then cd $current_dirs[$i] ls break fi done } alias ex=extract_archive compdef '_files -g "*.gz *.tgz *.bz2 *.tbz *.zip *.rar *.tar *.lha"' extract_archive