bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: equivalent of Linux readlink -f in pure bash?


From: Stephane CHAZELAS
Subject: Re: equivalent of Linux readlink -f in pure bash?
Date: Tue, 9 Aug 2011 11:02:27 +0100
User-agent: slrn/pre1.0.0-18 (Linux)

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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]