NAME
FindBin::Bin - Absolute path to the executable's directory, with two normalization strategies for paths containing .. segments.
SYNOPSIS
# Exports two variables (and matching constant subs) for the
# directory containing the running script, plus two utilities:
use FindBin::Bin
qw(
$Bin # absolute path via File::Spec::canonpath
Bin # constant sub returning $Bin
$Bin_c # absolute path via canon_dir (stack-based '..' removal)
Bin_c # constant sub returning $Bin_c
pwd # absolute CWD, symlinks preserved (like "pwd -L")
canon_dir # remove '..' and '.' without touching the filesystem
);
# For paths with no '..' segments both variables are identical:
say $Bin; # /home/jowbloe/project/bin
say $Bin_c; # /home/jowbloe/project/bin
# They differ when the resolved path contains intermediate '..'
# segments. canonpath (used for $Bin) only removes a trailing
# '/..' and leading '/../'; canon_dir removes every '..':
# $0 = 'goes/../../up/script.pl', pwd = /home/jowbloe/project
say $Bin; # /home/jowbloe/project/goes/../../up (canonpath)
say $Bin_c; # /home/jowbloe/up (canon_dir)
# Both variables preserve symlinks -- neither calls Cwd::abs_path.
# If you need the physical (dereferenced) path, call abs_path()
# from Cwd yourself.
# Interactive invocations (perl -e, perl -E, perl -, debugger):
# $Bin_c = pwd() -- CWD as returned by pwd()
# $Bin = rel2abs(pwd()) -- canonpath of pwd() (equal for clean paths)
perl -MFindBin::Bin=Bin -e 'say Bin';
perl - < ../../foo/bar/bim;
# Named scripts: directory component of $0, with pwd() prepended
# when $0 is relative. Both are absolute at program startup.
use FindBin::Bin qw( pwd );
my $cwd = pwd; # same as "pwd -L" on *NIX
use FindBin::Bin qw( canon_dir );
my $path = canon_dir '/foo/bar/../bletch/./../blort';
# => '/foo/blort'
my $clamped = canon_dir '/foo/bar/../../../../../../../';
# => '/' (cannot '..' past root)
DESCRIPTION
This module computes two absolute-path forms of the directory that contains the running script ($0) and exports them at compile time in a BEGIN block. Both forms preserve symbolic links; they differ only in how they handle .. segments in the path.
$Bin and Bin()
$Bin is computed via File::Spec::rel2abs, which reduces to File::Spec::canonpath for an already-absolute path. canonpath performs string-level normalisation: it collapses repeated slashes, removes /./ sequences, and strips a leading /../ or a trailing /.., but it does not remove intermediate /../ segments such as /foo/bar/../baz.
For most scripts, where $0 contains no .., $Bin and $Bin_c are identical.
$Bin_c and Bin_c()
$Bin_c is computed via canon_dir(), which uses a stack algorithm to process every path component. It removes all .. and . segments regardless of position, producing the shortest equivalent absolute path without touching the filesystem.
Symlinks
Neither $Bin nor $Bin_c resolves symbolic links. Both are derived from pwd() (which behaves like pwd -L) and from $0 as Perl set it -- the path through which the script was invoked. If you need the physical path with symlinks dereferenced, use Cwd::abs_path() directly.
Resolving the working directory
Interactive invocations
When $0 is -e, -, or interactive (one-liner, stdin, or debugger), the directory is taken from pwd():
$Bin_c = pwd()
$Bin = rel2abs( pwd() ) # == canonpath( pwd() ) for clean paths
Named script files
When $0 holds a file path the directory component is extracted via splitpath. A relative directory has pwd() prepended before normalisation:
$Bin = catpath( $vol, rel2abs( $raw ) )
$Bin_c = catpath( $vol, canon_dir( $raw ) )
where $raw is the absolute directory string.
Both variables are defined as read-only ref-to-constant scalars and constant subs; they do not change after the BEGIN block runs.
pwd()
Returns the same value as "pwd -L" -- an absolute path to the CWD with symbolic links left as-is. On *NIX and Cygwin it validates $ENV{PWD} against the inode of '.' and falls back to Cwd::getcwd() (which resolves symlinks) only when they disagree. On VMS it uses $ENV{DEFAULT}; on MSWin32 it uses Cwd::getcwd().
The result is memoised; pwd() always returns the value from program startup.
canon_dir()
Accepts an absolute or relative path and returns an absolute path with all . and .. components removed via a stack algorithm. Symlinks are not consulted. A relative input has pwd() prepended.
canon_dir '/foo/bar/../bim/../../bletch';
# => '/bletch' (.. backs off bar, then bim, then foo)
canon_dir '/foo/bar/../../../../../../../';
# => '/' (cannot go above root)