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
  builtin cd $*
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.

Author: Copyright © 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 © 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 © 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 © 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 © 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
 
examples/functions.txt · Last modified: 2013/01/04 10:52 by francisco