[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
signature.asc
Description: OpenPGP digital signature