All of those mechanisms break if the script is being called by a symlink, and particularly so if nested symlinks are involved. You need to readlink($0) if (-l $0) first, and then check, and even then, it won't give you the same output as FindBin::RealBin.
Create the following directory structure in /var/tmp. Set up directories as follows (you'll need root for /usr/local/bin, so feel free to make the last step anywhere else in your path that you'd like):
cd /var/tmp
mkdir mydir
mkdir datadir
mkdir otherdir
cd otherdir
ln -s ../mydir symdir
Now take the following code and put it in /var/tmp/mydir/myname.pl:
#!/usr/bin/perl
use strict;
use warnings;
use FindBin;
use File::Basename qw( dirname );
use File::Spec::Functions qw( rel2abs );
my $name = $0;
$name = readlink($name) if(-l $name);
print "Finding a data path:\n\n";
print 'dirname($name):',dirname($name),"/../datadir\n";
print 'dirname(rel2abs($name)):',dirname(rel2abs($name)),"/../datadir\
+n";
print 'dirname($0):',dirname($0),"/../datadir\n";
print 'dirname(rel2abs($0)):',dirname(rel2abs($0)),"/../datadir\n";
print '$FindBin::RealBin:',$FindBin::RealBin,"/../datadir\n";
Symlink /var/tmp/symdir/myname.pl to /usr/local/bin/myname (or somewhere else on your path, if you can't or don't want to tamper with a system directory). Run 'myname'. You get:
Finding a data path:
dirname($name):/var/tmp/otherdir/symdir/../datadir
dirname(rel2abs($name)):/var/tmp/otherdir/symdir/../datadir
dirname($0):/usr/local/bin/../datadir
dirname(rel2abs($0)):/usr/local/bin/../datadir
$FindBin::RealBin:/var/tmp/mydir/../datadir
Only FindBin correctly points you to the correct data directory location.
Frankly, even without symlink forests, FindBin is more readable, though.
|