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 program, plus two utilities.
# $Bin defaults to the logical path; pass 'abspath' to get physical.
use FindBin::Bin
qw(
$Bin # logical path by default; physical with 'abspath' (see below)
Bin # constant sub returning same value as $Bin
$Bin_l # logical path via canon_dir (stack-based '..' removal, like pwd -L)
Bin_l # constant sub returning $Bin_l
$Bin_p # physical path via Cwd::abs_path (resolves symlinks, like pwd -P)
Bin_p # constant sub returning $Bin_p
pwd # absolute CWD, symlinks preserved (like "pwd -L")
canon_dir # remove '..' and '.' without touching the filesystem
);
# $Bin defaults to the logical path (same as $Bin_l).
# Pass 'abspath' to get the physical path (same as $Bin_p):
use FindBin::Bin qw( $Bin ); # $Bin == $Bin_l (logical, default)
use FindBin::Bin qw( $Bin abspath ); # $Bin == $Bin_p (physical)
# For paths with no symlinks, all three variables are identical:
say $Bin; # /home/jowbloe/project/bin
say $Bin_l; # /home/jowbloe/project/bin (canon_dir, logical)
say $Bin_p; # /home/jowbloe/project/bin (abs_path, physical)
# They differ when the program's directory path contains symlinks.
# If /home/jowbloe is a symlink to /real/home/jowbloe:
say $Bin_l; # /home/jowbloe/project/bin (symlinks preserved)
say $Bin_p; # /real/home/jowbloe/project/bin (symlinks resolved)
# Interactive invocations (perl -e, perl -E, perl -, debugger):
# $Bin_l = pwd() -- CWD as returned by pwd()
# $Bin_p = abs_path(pwd()) -- CWD with symlinks resolved
perl -MFindBin::Bin=Bin -e 'say Bin';
perl - < ../../foo/bar/bim;
# Named programs: directory component of $0, with pwd() prepended
# when $0 is relative. All variables 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 three absolute-path forms of the directory that contains the running program ($0) and exports them at compile time in a BEGIN block.
$Bin and Bin()
$Bin is a configurable alias. By default it equals $Bin_l (the logical path). Passing 'abspath' in the import list makes $Bin equal $Bin_p (the physical path) in the calling package:
use FindBin::Bin qw( $Bin ); # $Bin == $Bin_l (default)
use FindBin::Bin qw( $Bin abspath ); # $Bin == $Bin_p
Bin() follows the same logic: it is aliased to Bin_l() or Bin_p() depending on the abspath flag.
$Bin_l and Bin_l()
$Bin_l ("logical", like pwd -L) is computed via canon_dir(), a stack algorithm that removes all .. and . segments without touching the filesystem. Symbolic links in the path are preserved.
$Bin_p and Bin_p()
$Bin_p ("physical", like pwd -P) is computed via Cwd::abs_path(), which resolves all symbolic links. If abs_path fails, $Bin_l is used as a fallback.
Symlinks
$Bin_l preserves directory symlinks in the path (logical, like pwd -L). $Bin_p resolves them to the real on-disk location (physical, like pwd -P). They are identical when no symlinks appear in the directory path.
Example: two lib trees, one symlink
Consider a sandbox layout where /home/user/app is a directory symlink pointing to the real project under /work/projects/app:
/home/user/ # logical subtree
+-- lib/
| \-- UserLib.pm # visible only via $Bin_l
\-- app -> /work/projects/app # directory symlink
/work/projects/ # physical subtree
+-- lib/
| \-- WorkLib.pm # visible only via $Bin_p
\-- app/
\-- bin/
\-- script # $0 -- the running program
When script is invoked via the symlink path (/home/user/app/bin/script):
$Bin_l = /home/user/app/bin # symlink path preserved
$Bin_p = /work/projects/app/bin # symlink resolved
FindBin::libs (and any other code that walks up from $Bin) finds different lib/ directories depending on which variable it uses as the starting point.
Using $Bin_l (noabspath):
walk: /home/user/app/bin -> /home/user/app -> /home/user
lib found: /home/user/lib
use lib '/home/user/lib' # loads UserLib.pm
Using $Bin_p (abspath, the default):
walk: /work/projects/app/bin -> /work/projects/app -> /work/projects
lib found: /work/projects/lib
use lib '/work/projects/lib' # loads WorkLib.pm
This is the "regression testing via symlinks" pattern: place a directory symlink to the program's bin inside a test sandbox that has its own lib/ tree. Toggle between the sandbox libraries (logical) and the source-tree libraries (physical) with the abspath setting in FindBin::libs, or by choosing which variable to use directly.
The default $Bin equals $Bin_l unless the caller passes 'abspath' at import time (see "$Bin and Bin()").
Resolving the working directory
Interactive invocations
When $0 is -e, -, or interactive (one-liner, stdin, or debugger), the directory is taken from pwd():
$Bin_l = pwd()
$Bin_p = Cwd::abs_path( pwd() ) # resolves symlinks in CWD
Named program files
When $0 holds a file path:
$Bin_l = catpath( $vol, canon_dir( $raw ), '' ) # logical, '..' removed
$Bin_p = catpath( $vol, abs_path( $raw ), '' ) # physical, symlinks resolved
where $raw is the absolute directory string derived from the directory component of $0 (with pwd() prepended for relative paths).
All 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)