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.

$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.

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)