123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- #! /bin/bash
- #
- # Symlink a existing file to a new location. Rename and link to old versions with datestamps.
- #
- # usage: link2 [options] target [link]
- # -v | --vrebose Echo command names
- # -d | --debug Additional debugging output
- # -h | --help This text
- # -n | --dry-run Do not execute
- # -r | --remove Remove link/file if it exists
- #
- # Examples:
- #
- # $ link2 -v /etc/passwd
- # ln -s /etc/passwd /home/george/bin/passwd
- #
- # $ link2 -v /etc/issue passwd
- # mv passwd passwd.20150609:052604EDT
- # ln -s /etc/issue passwd
- #
- # $ link2 -r -v /etc/issue passwd
- # link2: passwd already points to /etc/issue
- #
- # $ link2 -r -v /etc/issue passwd
- # rm -f passwd
- # ln -s /etc/issue passwd
- #
- # $ link2 -v /etc/passwd $HOME
- # ln -s /etc/passwd /home/george/passwd
- #
- #
- # Author:
- # George Jones
- set -e -u
- PROG_NAME=$0
- PROG_NAME=`basename $0`
- SHORT_OPTS='vdhnrs:'
- LONG_OPTS='verbose,debug,dry-run,help,remove,stack-size:'
- OPTS=`getopt -o $SHORT_OPTS --long $LONG_OPTS -n 'parse-options' -- "$@"`
- function usage() {
- cat <<END >&2
- usage: $PROG_NAME [options] target [link]
- -v | --verbose Echo command names
- -d | --debug Additional debugging output
- -h | --help This text
- -n | --dry-run Do not execute
- -r | --remove Remove link/file if it exists
- END
- exit 1
- }
- if [ $? != 0 ] ; then echo "Failed parsing options." >&2 ; exit 1 ; fi
- eval set -- "$OPTS"
- # Default values
- VERBOSE=false
- HELP=false
- DRY_RUN=false
- STACK_SIZE=0
- DEBUG=false
- REMOVE=false
- # Set user selected options
- while true; do
- case "$1" in
- -v | --verbose ) VERBOSE=true; shift ;;
- -d | --debug ) DEBUG=true; shift ;;
- -h | --help ) HELP=true; shift ;;
- -n | --dry-run ) DRY_RUN=true; shift ;;
- -r | --remove ) REMOVE=true; shift ;;
- -s | --stack-size ) STACK_SIZE="$2"; shift; shift ;;
- -- ) shift; break ;;
- * ) break ;;
- esac
- done
- if $DEBUG; then
- VERBOSE=true
- fi
- if $DEBUG; then
- echo VERBOSE=$VERBOSE
- echo DEBUG=$DEBUG
- echo HELP=$HELP
- echo DRY_RUN=$DRY_RUN
- echo REMOVE=$REMOVE
- echo STACK_SIZE=$STACK_SIZE
- fi
- # validate arguments
- if [[ "$STACK_SIZE" =~ '"^[0-9]+$' ]]; then
- echo "$PROG_NAME: stack_size must be an integer. Got /$STACK_SIZE/" >&2
- usage
- fi
- # get file arguments
- if [ "$#" -lt 1 ]; then
- echo $PROG_NAME: Missing target
- usage
- fi
- if $HELP; then
- usage
- fi
- file=$1
- whereto=${2:-"${PWD}"}
- # figure out the link target, make sure it exists
- target="`readlink -f $file`"
- if $DEBUG; then echo target $target; fi
- if [ ! -e ${target} ]; then
- echo $0: ${target} does not exist >&2
- exit 1
- fi
- # figure out the link source, using basename of target
- base=`basename $file`
- if [ -d `readlink -f "${whereto}"` ]; then
- link="${whereto}""/""${base}"
- else
- link=${whereto}
- fi
- # Remove link if it exists
- if $REMOVE && [ -h $link -o -f $link ]; then
- if $DRY_RUN || $VERBOSE; then
- echo rm -f $link
- fi
- if ! $DRY_RUN; then
- rm -f $link
- fi
- fi
- # move any pre-existing file to a dated save version, unless it's the same
- now=`date "+%Y%m%d:%H%M%S%Z"`
- if [ -e ${link} ]; then
- # TODO abort here if target already points to target.
- expandedLink=`readlink -e ${link}`
- expandedTarget=`readlink -e ${target}`
- if [ ${expandedLink} == ${expandedTarget} ]; then
- echo $PROG_NAME: ${link} already points to ${target} >&2
- exit 0
- fi
- if $DRY_RUN || $VERBOSE; then
- echo mv ${link} "${link}.${now}"
- fi
- if ! $DRY_RUN; then
- mv ${link} "${link}.${now}"
- fi
-
- fi
- # finally, make the link
- if $DEBUG; then echo target $target >&2; fi
- if $DRY_RUN || $VERBOSE; then
- echo ln -s ${target} ${link}
- fi
- if ! $DRY_RUN; then
- ln -s ${target} ${link}
- fi
|