coreutils
[Top][All Lists]
Advanced

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

Re: command for relative path


From: Eric Blake
Subject: Re: command for relative path
Date: Sat, 12 Nov 2011 11:45:56 -0700
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:7.0.1) Gecko/20110930 Thunderbird/7.0.1

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?

-- 
Eric Blake   address@hidden    +1-801-349-2682
Libvirt virtualization library http://libvirt.org

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

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