2011-08-09, 11:29(+02), Bernd Eggink: > On 09.08.2011 03:44, Jon Seymour wrote: >> Has anyone ever come across an equivalent to Linux's readlink -f that >> is implemented purely in bash? > > You can find my version here: > > http://sudrala.de/en_d/shell-getlink.html > > As it contains some corrections from Greg Wooledge, it should handle > even pathological situations. ;) [...]
> function getlink # ([-l] path) Why use the ksh syntax instead of the standard one? > { > # Path of the file a symbolic link is pointing to. > # -l: follow link chain, print last target > # no option: print 1st target unchanged > > typeset dir file last link opt oldPWD=$PWD ret=0 > > (( OPTIND = 1 )) > > while getopts "l" opt > do > case $opt in > (l) last=1 > ;; > esac > done > > shift $(( OPTIND - 1 )) > file=$1 > > if [[ $last ]] # last link > then > while true > do > dir=$(dirname "$file") What if $file starts with "-"? > [[ ! -d $dir ]] && > { > ret=1 > break > } > > # remove slashes at end > > while [[ $file == */ ]] > do > file=${file%/} > done What if $file is "/" > file=${file##*/} # file name > command cd -P "$dir" What if that command fails? > [[ ! -h $file ]] && break What if there are symlinks in the path components? > link=$(command ls -l -- "$file"; printf x) Good point about command substitution discarding trailing newlines. I forgot that in the solution I gave. > link=${link%$'\nx'} > remove="$file -> " > file=${link#*"$remove"} > done > > printf "%s\n" "$PWD/$file" > command cd $oldPWD What if $oldPWD has blanks or wildcards? > elif [[ ! -h $file ]] # 1st link > then > printf "%s\n" "$file" > else > link=$(ls -l "$file") > printf "%s\n" "${link##*-> }" What about trailing newlines here and links with "-> " in their path. > fi > > return $ret What if $IFS contains 0 or 1? > } > > declare -fc getlink What's the -c about? -- Stephane