From: Akim Demaille <[EMAIL PROTECTED]>
Date: 06 Jul 2000 17:03:52 +0200
echo $dir | sed '/^\/*$/!s,//*$,,;s,[^/]*$,,;s,//*$,/,;/^\/$/!s,/$,,'
It's not portable to use "echo". On some hosts, "echo" mishandles
backslashes and/or names beginning with "-".
It's more portable to use "expr", like this:
expr \
"X$dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
"X$dir" : 'X\(//\)[^/]' \| \
"X$dir" : 'X\(//\)$' \| \
"X$dir" : 'X\(/\)' \| \
. : '\(.\)'
This implementation is portable to all POSIX.1 or traditional hosts,
including the treatment of leading //.
Here is a shell script (derived from yours) that illustrates how this
implementation compares to alexandre's and GNU dirname's output. The
expr implementation agrees with GNU dirname except in some cases with
leading //, where it generates output that is more portable than GNU
dirname's output.
#! /bin/sh
format="%12s %12s %12s %12s\n"
# alexandre, GNU dirname, eggert
printf "$format" "dir" "al" "dn" "eg"
for dir in //1 /1 ./1 ../../2 \
'' 1 ///1 ///1/2 ///1//2 \
//1/ /1/ ./1/ ../../2 \
//1/3 /1/3 ./1/3 ../../2/3 \
//1/3/// /1/3/// ./1/3/// ../../2/3/// \
//1//3/ /1//3/ ./1//3/ ../../2//3/
do
al=`echo "$dir" | sed '/^\/*$/!s,//*$,,;s,[^/]*$,,;s,//*$,/,;/^\/$/!s,/$,,'`
dn=`command dirname "$dir"`
eg=`expr \
"X$dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
"X$dir" : 'X\(//\)[^/]' \| \
"X$dir" : 'X\(//\)$' \| \
"X$dir" : 'X\(/\)' \| \
. : '\(.\)'
`
printf "$format" "$dir" "$al" "$dn" "$eg"
# echo "$dir $al $dn"
done
$ sh dirname.sh
dir al dn eg
//1 / / //
/1 / / /
./1 . . .
../../2 ../.. ../.. ../..
. .
1 . .
///1 / / /
///1/2 ///1 ///1 ///1
///1//2 ///1 ///1 ///1
//1/ / / //
/1/ / / /
./1/ . . .
../../2 ../.. ../.. ../..
//1/3 //1 //1 //1
/1/3 /1 /1 /1
./1/3 ./1 ./1 ./1
../../2/3 ../../2 ../../2 ../../2
//1/3/// //1 //1 //1
/1/3/// /1 /1 /1
./1/3/// ./1 ./1 ./1
../../2/3/// ../../2 ../../2 ../../2
//1//3/ //1 //1 //1
/1//3/ /1 /1 /1
./1//3/ ./1 ./1 ./1
../../2//3/ ../../2 ../../2 ../../2