Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

readlink replacement

Status
Not open for further replies.

feherke

Programmer
Aug 5, 2002
9,541
RO
Hi

The [tt]readlink[/tt] command is usefull to find out the target of a symbolic link. Any idea for similar commands, in case [tt]readlink[/tt] is not available ?

Ok, I can write a function, thats not a problem. ( No error checking in below codes. )
Code:
readlink() { ls -ld "$1" | sed 's/.*-> //'; }
[gray]# or[/gray]
readlink() { find "$1" -mindepth 0 -maxdepth 0 -printf "%l\n"; }
But while a [tt]readlink()[/tt] system call is available, I hope there is a somehow standard and faster way to do this.

Thanks.

Feherke.
 
Under what OS's is readlink available as a command, out of curiosity?

I'm not aware of anything else to do that, I would have suggested your first function, or ls -L if you just needed to get the attributes of the targeted file, or check for its existence.

Annihilannic.
 
PN=`basename "$0"` # Resolvelink


MAXHOPS=30

Usage () {
echo >&2 "$PN - resolve symbolic links.
usage: $PN [file | directory] [...]

Each line starts with an classification character:
# absolute path name of the starting link
> link to another link
+ link resolved (entry is listable)
- link resolved (entry is invalid)
! error, i.e. too many hops (more than $MAXHOPS)"
exit 1
}

Msg () {
for MsgLine
do echo >&2 "$PN: $MsgLine"
done
}

Fatal () { Msg "$@"; exit 1; }

RelToAbs () {
for RelPath
do
Dir=`dirname "$RelPath"`
Dir=`cd $Dir; pwd`
# Work around for SOLARIS 2.5 ksh93 bug ("cd" prints new directory)
Dir=`echo "$Dir" | sed q`
case "$RelPath" in
*/) Base=`basename \`echo "$RelPath"\` | sed 's:/[/]*$::'`;;
*) Base=`basename "$RelPath"`;;
esac
echo "$Dir/$Base"
done
}

Resolve () {
for SymLink
do
L=`RelToAbs "$SymLink"`
Indent=
HopCount=0
(
while [ -h "$L" ]
do
if [ -z "$Indent" ]
then
echo "# $L"
Indent="> "
else
echo "${Indent}$L `RelToAbs \"$L\"`"
fi

ParentDir=`dirname "$L"`
[ -n "$ParentDir" -a -d "$ParentDir" ] || {
Msg "could not determine parent directory for $L"
break
}
cd "$ParentDir"
BaseName=`basename "$L"`
[ -n "$BaseName" ] || {
Msg "could not determine basename for $L"
break
}
Ref=`ls -ld "$BaseName" | awk '{print $NF}'`
if [ -n "$Ref" ]
then
if [ "$L" != "$Ref" ]
then
L="$Ref"
else # direct loop (i.e. "a -> a")
echo "! loop detected - $Ref (`pwd`)"
break
fi
else
Msg "could not list link $L - should not occur"
break;
fi
HopCount=`expr $HopCount + 1`
if [ ${HopCount:=0} -gt $MAXHOPS ]
then
echo "! too many links (more than $MAXHOPS): $Ref (`pwd`)"
break
fi
done

# Ref contains the last (relative) path of the symbolical
# link chain

if [ X`ls -d "$Ref" 2>/dev/null` != X ]
then
echo "+ $Ref `RelToAbs $Ref`"
else
echo "- $Ref"
fi
)
done
}

verbose=no
set -- `getopt h "$@"`
while [ $# -gt 0 ]
do
case "$1" in
-v) verbose=yes;;
--) shift; break;;
-h) Usage;;
-*) Usage;;
*) break;; # First file name
esac
shift
done

[ $# -lt 1 ] && set -- * # Default: current directory

find "$@" -type l -print |
while read Link ignore
do
[ -h "$Link" ] || continue
Resolve "$Link"
done

Mike

"A foolproof method for sculpting an elephant: first, get a huge block of marble, then you chip away everything that doesn't look like an elephant."

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top