#!/bin/bash # author Jens Getreu # version 1.1.0 set -e declare SCRIPT_NAME="$(basename $0)" function usage { echo "Usage: $SCRIPT_NAME -l " echo " " echo echo " $SCRIPT_NAME -l links source file/dir" echo " into destination directory using the shortest possible" echo " relative path." echo " It works like "ln -s" but with relative paths." exit 1 } # author of this fuction: juancn # http://stackoverflow.com/questions/2564634/ function find_relpath () { #echo "find_relpath $# parameters"; echo "$@" declare base=$1 declare target=$2 declare -a base_part=() declare -a target_part=() #Split path elements & canonicalize OFS="$IFS"; IFS='/' bpl=0; for bp in $base; do case "$bp" in ".");; "..") let "bpl=$bpl-1" ;; *) base_part[${bpl}]="$bp" ; let "bpl=$bpl+1";; esac done tpl=0; for tp in $target; do case "$tp" in ".");; "..") let "tpl=$tpl-1" ;; *) target_part[${tpl}]="$tp" ; let "tpl=$tpl+1";; esac done IFS="$OFS" #Count common prefix common=0 for (( i=0 ; i<$bpl ; i++ )); do if [ "${base_part[$i]}" = "${target_part[$common]}" ] ; then let "common=$common+1" else break fi done #Compute number of directories up let "updir=$bpl-$common" || updir=0 #if the expression is zero, 'let' fails #trivial case (after canonical decomposition) if [ $updir -eq 0 ]; then #echo ./ result="./" fi #Print updirs for (( i=0 ; i<$updir ; i++ )); do #echo -n ../ result="${result}../" done #Print remaining path for (( i=$common ; i<$tpl ; i++ )); do if [ $i -ne $common ]; then #echo -n "/" result="${result}/" fi if [ "" != "${target_part[$i]}" ] ; then #echo -n "${target_part[$i]}" result="${result}${target_part[$i]}" fi done #One last newline } # Start if [ $# -ne 3 ]||[ "$1" != "-s" ]; then usage;exit 1; fi #echo "main $# parameters"; echo "$@" # compute shortest path find_relpath "$3" "$2" #quotes for not splitting whitespaces # link it into $3 echo "executing: cd <$3>; ln -s <$result> <.>" pushd . >/dev/null cd "$3" ln -s "$result" . exit_code=$? popd >/dev/null exit $exit_code