On Sat, Nov 12, 2011 at 12:45 PM, Eric Blake <ebl...@redhat.com> wrote:
> On 11/12/2011 09:16 AM, Peng Yu wrote:
>> Hi,
>>
>> coreutils can give abspaths ('readlink -f -e'). But I'm not able to
>> find a command for relative paths.
>
> I had to go chase down python documentation to see what you wanted,
> since you didn't give an example:
>
>>
>> print os.path.relpath(path, start)
>
> http://docs.python.org/library/os.path.html
>>> os.path.relpath(path[, start])
>>>
>>>     Return a relative filepath to path either from the current directory or 
>>> from an optional start point.
>
> Ah, so the idea is that python has a function that computes a relative
> pathname to one path given a starting point:
>
> $ relpath /usr/bin /tmp
> ../usr/bin
> $ relpath /usr/bin /usr/share
> ../bin
>
> This seems like you could do it in shell without resorting to python, by
> computing a canonical name for both the destination and the starting
> point, then comparing common prefixes, and for every directory component
> that differs after the common prefix, replacing the directory with
> '../'.  This has been done before; for example, this is from gnulib-tool:
>
> # func_relativize DIR1 DIR2
> # computes a relative pathname RELDIR such that DIR1/RELDIR = DIR2.
> # Input:
> # - DIR1            relative pathname, relative to the current directory
> # - DIR2            relative pathname, relative to the current directory
> # Output:
> # - reldir          relative pathname of DIR2, relative to DIR1
> func_relativize ()
> {
>  dir0=`pwd`
>  dir1="$1"
>  dir2="$2"
>  sed_first='s,^\([^/]*\)/.*$,\1,'
>  sed_rest='s,^[^/]*/*,,'
>  sed_last='s,^.*/\([^/]*\)$,\1,'
>  sed_butlast='s,/*[^/]*$,,'
>  while test -n "$dir1"; do
>    first=`echo "$dir1" | sed -e "$sed_first"`
>    if test "$first" != "."; then
>      if test "$first" = ".."; then
>        dir2=`echo "$dir0" | sed -e "$sed_last"`/"$dir2"
>        dir0=`echo "$dir0" | sed -e "$sed_butlast"`
>      else
>        first2=`echo "$dir2" | sed -e "$sed_first"`
>        if test "$first2" = "$first"; then
>          dir2=`echo "$dir2" | sed -e "$sed_rest"`
>        else
>          dir2="../$dir2"
>        fi
>        dir0="$dir0"/"$first"
>      fi
>    fi
>    dir1=`echo "$dir1" | sed -e "$sed_rest"`
>  done
>  reldir="$dir2"
> }
>
> Doing it in fewer processes seems possible with something like a single
> awk script, although I haven't tried writing one; at any rate, awk would
> be more portable than python for the same task.
>
> But yes, providing this as an alternative mode of coreutils' realpath
> instead of scripting it in shell or awk seems like a useful addition -
> would you care to submit a patch?

Sure.

Should this be added to an existing coreutils' command or add a new
command to coreutils? Personally I'd prefer to add a command called
relpath. But I'm not sure the standard organization in coreutils.

-- 
Regards,
Peng

Reply via email to