Env-Path-0.19/0000755006655200705100000000000012144541575012111 5ustar dsbccusersEnv-Path-0.19/examples/0000755006655200705100000000000012144541575013727 5ustar dsbccusersEnv-Path-0.19/examples/Whence0000755006655200705100000000316207777262203015074 0ustar dsbccusers#!/usr/local/bin/perl # This is analogous to the ksh 'whence' builtin, except that its # arguments are treated as patterns. Thus "Whence foo*" will print # the paths of all programs whose names match foo*. use Env::Path qw(:all); use constant MSWIN => $^O =~ /MSWin32|Windows_NT/i ? 1 : 0; use Getopt::Long; my %opt; GetOptions(\%opt, qw(first_only help)); exit(system("perldoc $0") >> 8) if $opt{help}; # In Windows, the cwd is always implicitly at the front of PATH. if (MSWIN) { require Cwd; (my $cwd = Cwd::getcwd()) =~ s%/%\\%g; PATH->Remove($cwd); PATH->Prepend($cwd); } for my $name (@ARGV) { $name .= '.*' if MSWIN && $name !~ /(?:\.\w+|\*)$/; for (PATH->Whence($name)) { print "$_\n"; last if $opt{first_only}; } } __END__ =head1 NAME Whence - Perl implementation/extension of ksh 'whence' builtin =head1 SYNOPSIS Whence foo Whence '?sh' Whence '*stat' Whence -f foo\* =head1 DESCRIPTION This is a Perl implementation of the I B builtin, similar to I B or I B. It differs from these in two ways: (1) it finds all occurrences of its arguments on PATH rather than just the first and (2) it treats its arguments as patterns, such that C will return all commands that I with C rather than looking for a literal 'cat*'. =head1 AUTHOR David Boyce =head1 COPYRIGHT Copyright (c) 2000-2002 David Boyce. All rights reserved. This Perl program is free software; you may redistribute and/or modify it under the same terms as Perl itself. =head1 SEE ALSO perl(1), ksh(1), "perldoc Env::Path" =cut Env-Path-0.19/examples/Whence.bat0000755006655200705100000000124611044377407015635 0ustar dsbccusers@echo off REM Wrapper bat script that calls the perl script of the same name with a .pl REM extension (in the same directory). Can be easily reused by making a copy REM and renaming the copy to be the same as your new .pl script, except with a REM .bat extension. In a UNIX environment, symlinks could to the job even better REM REM Author: Taylor Jones REM Get the fully qualified path name of this script set PLSCRIPT=%~f0 REM Strip off the '.bat' and replace it with nothing. set PLSCRIPT=%PLSCRIPT:~0,-4% REM Or replace it with something if preferred: REM set PLSCRIPT=%PLSCRIPT:~0,-4%.pl REM Run the resulting perl script. perl %PLSCRIPT% %* Env-Path-0.19/Makefile.PL0000755006655200705100000000044207121715535014064 0ustar dsbccusersuse ExtUtils::MakeMaker; WriteMakefile( 'NAME' => 'Env::Path', 'VERSION_FROM' => 'Path.pm', # finds $VERSION 'EXE_FILES' => [ 'envpath' ], 'PREREQ_PM' => {}, 'dist' => { COMPRESS => 'gzip --force --best', TAR => 'gtar', TARFLAGS => '--mode=u+w -cvf', }, ); Env-Path-0.19/META.yml0000664006655200705100000000072512144541575013370 0ustar dsbccusers--- #YAML:1.0 name: Env-Path version: 0.19 abstract: ~ author: [] license: unknown distribution_type: module configure_requires: ExtUtils::MakeMaker: 0 build_requires: ExtUtils::MakeMaker: 0 requires: {} no_index: directory: - t - inc generated_by: ExtUtils::MakeMaker version 6.55_02 meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 Env-Path-0.19/README0000644006655200705100000000223707362733471013001 0ustar dsbccusersEnv::Path presents an object-oriented interface to "path variables", defined as that subclass of environment variables which name an ordered list of filesystem elements separated by a platform-standard separator (typically ':' on UNIX and ';' on Windows). Of course, core Perl constructs such $ENV{PATH} .= ":/usr/local/bin"; will suffice for most uses. Env::Path is for the others; cases where you need to insert or remove interior path entries, strip redundancies, operate on a pathvar without having to know whether the current platform uses ":" or ";", operate on a pathvar which may have a different name on different platforms, etc. The OO interface is slightly unusual in that the environment variable is itself the object, and the constructor is Env::Path->AUTOLOAD; thus Env::Path->MANPATH; will bless $ENV{MANPATH} into its package while leaving it otherwise unmodified (with the exception of possible autovivification). Unlike most objects, this is a scalar and thus can have only one attribute; its value. In other words, Env::Path simply defines a set of methods a path variable may call on itself without changing the variable's value or other semantics. Env-Path-0.19/envpath0000644006655200705100000002103707741546045013510 0ustar dsbccusers#!/usr/local/bin/perl use File::Basename; use Getopt::Long; use constant MSWIN => $^O =~ /MSWin32|Windows_NT/i ? 1 : 0; sub usage { my $msg = shift; my $rc = (defined($msg) && !$msg) ? 0 : 2; if ($rc) { select STDERR; print $msg if $msg && $msg =~ /^\d+$/; } my $prog = basename($0, qw(.pl)); print < to within 'VAR' -P TOKEN Prepend TOKEN to the path variable named 'VAR' -I dir,(-|+)TOKEN] Insert TOKEN before (-) or after (+) 'dir' in VAR -L [VAR] List specified pathvar(s) in one-entry-per-line fmt -N Remove entries which don't exist -R TOKEN Remove specified dir from path -S [VAR] Print specified pathvars in form suitable for `eval` -U Remove redundant entries from path -W file Like 'whence' ksh builtin - look for 'file' on PATH Examples: $prog PATH=/tools/\@PLATFORM@/bin,\@PATH@ -- printenv PATH $prog CLASSPATH=\@CLASSPATH@,\@JAVA_HOME@/classes printenv CLASSPATH $prog -E LD_RUN_PATH -A /usr/openwin/lib -U -- ld ... $prog -E LD_RUN_PATH -I /usr/openwin/lib,-\@LD_LIBRARY_PATH@ ld ... $prog -L $prog -E CLASSPATH -L $prog -C /opt/netscape=/usr/local/netscape -L eval `$prog -N -U -R /usr/ucb -S` eval `$prog -E LD_RUN_PATH -I /usr/openwin/lib,-/usr/local/lib -S` $prog -W cat In the above, TOKEN refers to a string which may optionally contain references to environment variables in the form \@VAR@. These will be replaced by the value \$VAR, and the commas will be replaced by the appropriate path separator (':' or ';') for the current platform. See "perldoc $prog" and "perldoc Env::Path" for full documentation. EOF exit $rc; } sub expand { my $ev = shift; while (my($token) = ($ev =~ m%@(\w+)@%)) { $ev =~ s%\@$token@%$ENV{$token}%; } return $ev; } usage() if !@ARGV; my @Paths; while (my($var, $where, $str) = ($ARGV[0] =~ m%^(\w+)([=+]+)(.*)%)) { my $param = shift; push(@Paths, $var); my @val = split(/,/, $str); for (@val) { $_ = expand($_) } my $dsep = MSWIN ? ';' : ':'; if ($where eq '=') { $ENV{$var} = join($dsep, @val); } elsif ($where eq '+=') { $ENV{$var} = join($dsep, @val, $ENV{$var}); } elsif ($where eq '=+') { $ENV{$var} = join($dsep, $ENV{$var}, @val); } else { die "Error: $0: malformed parameter '$param'\n"; } } my %opt; my($opt_help, $opt_verbose); { local $Getopt::Long::passthrough = 1; GetOptions('help' => \$opt_help, 'verbose' => \$opt_verbose); usage() if $opt_help; } local $Getopt::Long::order = $REQUIRE_ORDER; GetOptions(\%opt, qw(Env=s Append=s@ Change=s@ Prepend=s@ Insert=s@ Remove=s@ Nonexistent Uniqify List:s@ Shell:s@ Whence=s) ); usage() if !@ARGV && !($opt{List} || $opt{Shell} || $opt{Whence}); if (%opt) { require Env::Path; push(@Paths, $opt{Env}) if $opt{Env}; push(@Paths, @{$opt{List}}) if $opt{List}->[0]; push(@Paths, @{$opt{Shell}}) if $opt{Shell}->[0]; push(@Paths, 'PATH') if !@Paths; my $var = $Paths[-1] || 'PATH'; my $path = eval "Env::Path->$var"; for (@{$opt{Prepend}}) { $path->Prepend(expand($_)) } for (@{$opt{Append}}) { $path->Append(expand($_)) } for (@{$opt{Remove}}) { $path->Remove(expand($_)) } for (@{$opt{Change}}) { my($old, $new) = split '=', $_, 2; $path->InsertBefore($old, $new); $path->Remove(expand($old)) } $path->DeleteNonexistent if $opt{Nonexistent}; $path->Uniqify if $opt{Uniqify}; for (@{$opt{Insert}}) { if (!m%^(.+?),([+-])(.*)%) { warn "Warning: $0: malformed -Insert parameter '$_'\n"; next; } my($marker, $where, $insert) = (expand($1), $2, expand($3)); if ($where eq '-') { $path->InsertBefore($marker, $insert); } else { $path->InsertAfter($marker, $insert); } } if ($opt{List} && @{$opt{List}}) { usage(2) if ($opt{Shell} && @{$opt{Shell}}) || $opt{Whence}; for my $pathvar (@Paths) { my $path = eval "Env::Path->$pathvar"; for ($path->List) { print $_, "\n" } } exit 0; } elsif ($opt{Shell} && @{$opt{Shell}}) { usage(2) if $opt{Whence}; for my $pathvar (@Paths) { print Env::Path->$pathvar->Shell, "\n"; } exit 0; } elsif ($opt{Whence}) { for my $pathvar (@Paths) { my $path = eval "Env::Path->$pathvar"; for ($path->Whence($opt{Whence})) { print $_, "\n" } } exit 0; } } print STDERR "+ @ARGV\n" if $opt_verbose; if (MSWIN) { exit system @ARGV; } else { exec @ARGV; die "$0: $ARGV[0]: $!\n"; } __END__ =head1 NAME envpath - Advanced operations on path variables =head1 SYNOPSIS Run this script with the C<-help> option for usage details. =head1 DESCRIPTION Parses the command line, modifies the specified path variable(s), and execs the remaining arguments. There are two modes, B and B: =head2 SIMPLE MODE Simple mode presents an alternative, platform-independent syntax for specifying paths wherein the path separator is "," and environment variables can be expanded with @NAME@. For example envpath PATH=@PATH@,/usr/ucb -- printenv PATH appends C to C<$PATH> and execs I. The C<--> is optional. You can also specify prepending or appending by using C<+=> or C<=+> respectively: # place /usr/ucb at the front envpath PATH+=/usr/ucb -- printenv PATH # place /usr/ucb at the back envpath PATH=+/usr/ucb -- printenv PATH Simple mode requires only this script; it does not require Env::Path to be installed. =head2 ADVANCED MODE Advanced mode basically provides command-line access to the features of Env::Path (see), which must be installed. The C<-E> flag selects the path variable to operate on and other flags specify operations on it. E.g. envpath -E MANPATH -A /tmp -R /usr/share/man -N -U -- man ... would take MANPATH, append /tmp to it, remove any references to C, remove any dirs which don't exist (C<-N>) and remove redundant entries (C<-U>) before running I. The -Whence option allows patterns. Thus envpath -W "cat*" would find all programs on PATH which match cat*. =head1 CLEARCASE WINKINS A big part of the motivation for this script was for use with ClearCase builds; iff you know or care about ClearCase read on. Typically, during builds (and not just with ClearCase), pathvars such as PATH, CLASSPATH, and LD_LIBRARY_PATH must be strictly controlled. One choice is to force static values of these into the environment during the build process, another is to simply require/expect users to set their paths appropriately. Each of these can lead to subtle build or runtime errors, however, and makes it hard for new users to get up to speed since their personal environment must be just so. Another common choice is to use only full pathnames within the Makefile, avoiding reliance on search paths at all. This is often the best way to go but can suppress ClearCase winkins. For example, say you're generating ascii files of some type with a binary executable you just built: $(INCDIR)/foo.h: $(BINDIR)/foomaker $(BINDIR)/foomaker ... The problem with this is that $(BINDIR) likely contains a platform part such as 'solaris' or 'hpux', which makes it impossible to wink in the foo.h file on other platforms even though it's ascii. This same thing could come up even with a standard pre-built utility that's in different places on different platforms; C, for instance, is in /usr/bin on Linux and /usr/ccs/bin on Solaris. You could modify the path on the fly: $(INCDIR)/foo.h: $(BINDIR)/foomaker PATH=$(BINDIR)$(SEP)$$PATH foomaker ... but this suffers from the same problem: since $(BINDIR) and $PATH are expanded literally within the build script they'll suppress winkins. Here's a solution using I: $(INCDIR)/foo.h: $(BINDIR)/foomaker envpath PATH=@BINDIR@,@PATH@ foomaker ... This hides the evaluation of BINDIR and PATH such that I never sees anything but the literals, thus clearing the field for winkins. Of course I is capable of doing more than this, but it's the original reason it was written. =head1 AUTHOR David Boyce =head1 COPYRIGHT Copyright (c) 2000-2001 David Boyce. All rights reserved. This Perl program is free software; you may redistribute and/or modify it under the same terms as Perl itself. =head1 SEE ALSO perl(1), "perldoc Env::Path" =cut Env-Path-0.19/test.pl0000755006655200705100000000227707215550454013437 0ustar dsbccusers# Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl test.pl' my $final = 0; # Automatically generates an ok/nok msg, incrementing the test number. BEGIN { my($next, @msgs); sub printok { push @msgs, ($_[0] ? '' : 'not ') . "ok @{[++$next]}\n"; return !$_[0]; } END { if ($loaded) { print "\n1..", scalar @msgs, "\n", @msgs; } else { print "not ok 1\n"; } } } use Env::Path; $loaded = 1; $final += printok(1); my $p1 = Env::Path->XXXPATH(qw(aaa bbb ccc)); printok($p1->Name eq 'XXXPATH' && !@XXXPATH::ISA); my $p2 = Env::Path->new('YYYPATH', qw(aaa bbb ccc xxx yyy zzz c123)); $p2->Replace('^c.*', qw(/CC /XX)); printok($p2->Name eq 'YYYPATH'); $p1->Append($p2->List); $p1->Uniqify; $p1->DeleteNonexistent; printok($p1->List eq 0); Env::Path->PATH; PATH->Uniqify; PATH->DeleteNonexistent; printok(@PATH::ISA); Env::Path->ZZZPATH(PATH->List); ZZZPATH->Append('/nosuchdir'); ZZZPATH->Assign(ZZZPATH->List, $ENV{ZZZPATH}); printok(PATH->List eq (ZZZPATH->List - 2)/2); ZZZPATH->Uniqify; printok(PATH->List eq ZZZPATH->List - 1); ZZZPATH->DeleteNonexistent; printok(PATH->List eq ZZZPATH->List); Env-Path-0.19/Changes0000644006655200705100000000370112144541545013402 0ustar dsbccusersRevision history for Perl extension Env::Path. 0.01 Fri Jun 2 13:53:39 2000 - original alpha version. 0.02 Fri Jun 30 13:23:49 EDT 2000 - fixed bug in Insert*() methods - added ->Has method. 0.04 Mon Aug 14 13:56:33 EDT 2000 - added interface to ->Whence in envpath script - fixed a bug with -L and -S in envpath script 0.05 Mon Sep 11 13:31:25 EDT 2000 - doc fixes only 0.06 Thu Sep 14 13:51:55 EDT 2000 - fixed typo in InsertAfter that doubled up the insert - quoting bugfix for "envpath -S" on Windows - envpath allows comma-separated insert list, eg "envpath -I /usr/sbin,-/tmp,/var/tmp" 0.07 Wed Sep 27 22:14:30 EDT 2000 - Added import method allowing "use Env::Path qw(:all)" to bless all EV's at BEGIN time and so on. - Added -Change feature to envpath script. - envpath -S does automatic export 0.08 Tue Dec 12 20:21:43 EST 2000 - Added ->Replace method. 0.09 Thu Feb 15 14:20:26 EST 2001 - Added Shell method to allow same functionality inline as "envpath -S". 0.10 Thu Sep 6 14:46:30 EDT 2001 - Fixed a warning when the path EV is null - Added ListNonexistent method. - Fixed glob bug in ->Whence on Windows by using bsd_glob() 0.11 Thu Sep 20 11:24:41 EDT 2001 - Fixed ->Whence on Windows to work with UNC paths. 0.12 Tue Oct 16 00:28:52 EDT 2001 - Added a README. 0.14 Tue Feb 5 20:27:54 EST 2002 - Worked around a spurious warning with empty import list. 0.15 Mon Dec 2 18:43:05 EST 2002 - Renamed ->Has() to ->Contains(), leaving ->Has() as a deprecated alias (because Has() sounds too much like something from UNIVERSAL). 0.17 Fri Oct 24 11:10:34 EDT 2003 - Windows portability work (case issues and /-vs-\ stuff) - Fixed ->Whence on Windows to always look in cwd first (boo!) 0.18 Thu Nov 9 09:19:04 EST 2006 - Now looks explicitly at PATHEXT on Windows when testing -x. 0.19 Tue May 14 19:05:20 EDT 2013 - Fix for Cygwin as suggested by Brendan Byrd via https://rt.cpan.org/Ticket/Display.html?id=85120 Env-Path-0.19/MANIFEST0000644006655200705100000000025712144541575013246 0ustar dsbccusersChanges MANIFEST README Makefile.PL Path.pm envpath test.pl examples/Whence examples/Whence.bat META.yml Module meta-data (added by MakeMaker) Env-Path-0.19/Path.pm0000644006655200705100000003172412144541424013343 0ustar dsbccuserspackage Env::Path; $VERSION = '0.19'; require 5.004; use strict; use constant MSWIN => $^O =~ /MSWin|Windows_NT/i ? 1 : 0; use Config; my $dsep = $Config::Config{path_sep}; sub new { my $class = shift; my $pathvar = shift; my $pathref = \$ENV{$pathvar}; bless $pathref, $class; $pathref->Assign(@_) if @_; return $pathref if defined wantarray; eval "\@$pathvar\::ISA = '$class'"; } sub import { my $class = shift; return unless @_; my @list = @_; @list = keys %ENV if $list[0] eq ':all'; for my $pathvar (@list) { $class->new($pathvar); } } sub AUTOLOAD { my $class = shift; (my $pathvar = $Env::Path::AUTOLOAD) =~ s/.*:://; return if $pathvar eq 'DESTROY'; $class->new($pathvar, @_); } sub _class2ref { my $proto = shift; ref $proto ? $proto : \$ENV{$proto}; } sub PathSeparator { shift; $dsep = shift if @_; return $dsep; } sub Name { my $pathref = _class2ref(shift); for my $name (keys %ENV) { return $name if $pathref == \$ENV{$name}; } return undef; } sub List { my $pathref = _class2ref(shift); return split /$dsep/, $$pathref; } sub Contains { my $pathref = _class2ref(shift); my $entry = shift; my @list = $pathref->List; if (MSWIN) { for ($entry, @list) { $_ = lc($_); s%\\%/%g; } } my %has = map {$_ => 1} @list; return $has{$entry}; } *Has = \&Contains; # backward compatibility sub Assign { my $pathref = _class2ref(shift); $$pathref = join($dsep, @_); return $pathref; } sub Prepend { my $pathref = _class2ref(shift); $pathref->Remove(@_); $$pathref = $dsep.$$pathref if $$pathref; $$pathref = join($dsep, @_) . $$pathref; return $pathref; } sub Append { my $pathref = _class2ref(shift); $pathref->Remove(@_); $$pathref .= $dsep if $$pathref; $$pathref .= join($dsep, @_); return $pathref; } sub InsertBefore { my $pathref = _class2ref(shift); my $marker = shift; $pathref->Remove(@_); my $insert = join($dsep, map {split ','} @_); my $temp = $$pathref || ''; $$pathref = ''; for (split /$dsep/, $temp) { $_ ||= '.'; $$pathref .= $dsep if $$pathref; if ($marker && $_ eq $marker) { $$pathref .= $insert . $dsep; undef $marker; } $$pathref .= $_; } if (defined $marker) { $$pathref = $$pathref ? "$insert$dsep$$pathref" : $insert; } return $pathref; } sub InsertAfter { my $pathref = _class2ref(shift); my $marker = shift; $pathref->Remove(@_); my $insert = join($dsep, map {split ','} @_); my $temp = $$pathref || ''; $$pathref = ''; for (split /$dsep/, $temp) { $_ ||= '.'; $$pathref .= $dsep if $$pathref; $$pathref .= $_; if ($marker && $_ eq $marker) { $$pathref .= $dsep . $insert; undef $marker; } } if (defined $marker) { $$pathref = $$pathref ? "$$pathref$dsep$insert" : $insert; } return $pathref; } sub Remove { my $pathref = _class2ref(shift); return $pathref unless $$pathref; my %remove = map {$_ => 1} @_; if (MSWIN) { for (keys %remove) { (my $lcname = lc($_)) =~ s%\\%/%g; delete $remove{$_}; $remove{lc($_)} = 1; } } my @entries = map {$_ || '.'} split(/$dsep/, $$pathref); if (MSWIN) { my @left = (); for (@entries) { (my $lcname = lc($_)) =~ s%\\%/%g; push(@left, $_) unless $remove{$lcname}; } $$pathref = join($dsep, @left); } else { $$pathref = join($dsep, grep {!$remove{$_}} @entries); } return $pathref; } sub Replace { my $pathref = _class2ref(shift); return $pathref unless $$pathref; my $re = shift; my @temp = split /$dsep/, $$pathref; for (@temp) { $_ ||= '.'; if (/$re/) { $_ = join($dsep, map {split ','} @_); } } $$pathref = join($dsep, @temp); return $pathref; } sub ListNonexistent { my $pathref = _class2ref(shift); return $pathref unless $$pathref; my @missing = (); for (split /$dsep/, $$pathref) { push(@missing, $_) if $_ && ! -e $_; } return @missing; } sub DeleteNonexistent { my $pathref = _class2ref(shift); return $pathref unless $$pathref; my $temp = $$pathref; $$pathref = ''; for (split /$dsep/, $temp) { $_ ||= '.'; next if ! -e $_; $$pathref .= $dsep if $$pathref; $$pathref .= $_; } return $pathref; } sub Uniqify { my $pathref = _class2ref(shift); my %seen; my $temp = $$pathref || ''; $$pathref = ''; for (split /$dsep/, $temp) { $_ ||= '.'; my $entry = MSWIN ? lc($_) : $_; next if $seen{$entry}++; $$pathref .= $dsep if $$pathref; $$pathref .= $_; } return $pathref; } sub Whence { my $pathref = _class2ref(shift); my $pat = shift; my(@found, %seen); for my $dir (split /$dsep/, $$pathref) { $dir ||= '.'; $dir =~ s%[/\\]+$%%; $dir =~ s%([/\\])[/\\]+%$1%; # On &^#$ Windows we need to convert paths to use /, then glob # using bsd_glob because it will automatically ignore case, # then convert back to \ iff the original paths preferred it. # Without this some paths, esp UNC paths, get mixed up. # We also have to deal with PATHEXT. if (MSWIN) { for my $ext ('', split ';', $ENV{PATHEXT}) { (my $glob = "$dir/$pat$ext") =~ s%\\%/%g; my @matches = File::Glob::bsd_glob($glob); if ($dir eq '.' || $dir =~ m%\\%) { $glob =~ s%/%\\%g; for (@matches) { s%/%\\%g } } push(@found, grep {-f $_ && !$seen{$_}++} $glob, @matches); } } else { my $glob = "$dir/$pat"; my @matches = glob($glob); if ($^O =~ m%cygwin%i) { push(@found, grep {-f $_ && !$seen{$_}++} $glob, @matches); } else { push(@found, grep {-f $_ && -x _ && !$seen{$_}++} $glob, @matches); } } } return @found; } sub Shell { my $pathref = _class2ref(shift); my $name = $pathref->Name; my $winshell = MSWIN && !$ENV{SHELL}; my $str = "set " if $winshell; $str .= qq($name="$$pathref"); $str .= "; export $name" if !$winshell; return $str; } # Nothing to do here, just avoiding interaction with AUTOLOAD. sub DESTROY { } 1; __END__ =head1 NAME Env::Path - Advanced operations on path variables =head1 SYNOPSIS use Env::Path; # basic usage my $manpath = Env::Path->MANPATH; $manpath->Append('/opt/samba/man'); for ($manpath->List) { print $_, "\n" }; # similar to above using the "implicit object" shorthand Env::Path->MANPATH; MANPATH->Append('/opt/samba/man'); for (MANPATH->List) { print $_, "\n" }; # one-shot use Env::Path->PATH->Append('/usr/sbin'); # Windows-ish example use Env::Path qw(PATH); PATH->Append('C:\\Program Files\\Debugging Tools for Windows'); print "$_\n" for (PATH->List); # change instances of /usr/local/bin to an architecture-specific dir Env::Path->PATH->Replace('/usr/local/bin', "/usr/local/$ENV{PLATFORM}/bin"); # more complex use (different names for same semantics) my $libpath; if ($^O =~ /aix/) { $libpath = Env::Path->LIBPATH; } else { $libpath = Env::Path->LD_LIBRARY_PATH; } $libpath->Assign(qw(/usr/lib /usr/openwin/lib)); $libpath->Prepend('/usr/ucblib') unless $libpath->Contains('/usr/ucblib'); $libpath->InsertAfter('/usr/ucblib', '/xx/yy/zz'); $libpath->Uniqify; $libpath->DeleteNonexistent; $libpath->Remove('/usr/local/lib'); print $libpath->Name, ":"; for ($libpath->List) { print " $_" }; print "\n"; # simplest usage: bless all existing EV's as Env::Path objects use Env::Path ':all'; my @cats = PATH->Whence('cat*'); print "@cats\n"; =head1 DESCRIPTION Env::Path presents an object-oriented interface to I, defined as that subclass of I which name an ordered list of filesystem elements separated by a platform-standard I (typically ':' on UNIX and ';' on Windows). Of course, core Perl constructs such $ENV{PATH} .= ":/usr/local/bin"; will suffice for most uses. Env::Path is for the others; cases where you need to insert or remove interior path entries, strip redundancies, operate on a pathvar without having to know whether the current platform uses ":" or ";", operate on a pathvar which may have a different name on different platforms, etc. The OO interface is slightly unusual in that the environment variable is itself the object and the constructor is Env::Path->AUTOLOAD(); thus Env::Path->MANPATH; will bless $ENV{MANPATH} into its package while leaving it otherwise unmodified (with the exception of possible autovivification). Unlike most objects, this is a scalar and thus can have only one attribute; its value. In other words, Env::Path simply defines a set of methods a path variable may call on itself without changing the variable's value or other semantics. Also, while the object reference may be assigned and used in the normal style my $path = Env::Path->CLASSPATH; $path->Append('/opt/foo/classes.jar'); a shorthand is also available: Env::Path->CLASSPATH; CLASSPATH->Append('/opt/foo/classes.jar'); I.e. the name of the path variable may be used as a proxy for its object reference. This may be done at 'use' time too: use Env::Path qw(PATH CLASSPATH); # or qw(:all) to bless all EV's CLASSPATH->Append('/opt/foo/classes.jar'); The design is intended to make use of this module as lightweight as possible. Rather than creating a new object to manage an environment variable, the environment variable is provided a set of methods for self-modification but is otherwise left undisturbed and can be used in all normal ways. =head2 CLASS METHODS =over 4 =item * The constructor may have any name; it's assumed to name a I as defined above. Returns the object reference. =item * PathSeparator Returns or sets the platform-specific path separator character, by default I<:> on open platforms and I<;> on monopolistic ones. =back =head2 INSTANCE METHODS Unless otherwise indicated these methods return the object reference, allowing method calls to be strung together. All methods which take lists join them together using the value of CPathSeparator>. =over 4 =item * Name Returns the name of the pathvar. =item * Contains Returns true iff the specified entry is present in the pathvar. =item * Assign Takes a list and sets the pathvar to that value, separated by the current PathSeparator. =item * List Returns the current path in list format. =item * Prepend For each entry in the supplied list, removes it from the pathvar if present and prepends it, thus ensuring that it's present exactly once and at the front. =item * Append Analogous to Prepend. =item * InsertBefore Takes a and a list, inserts the list just before the first instance of the . If I is not found, works just like I. As with I, duplicates of the supplied entries are removed. =item * InsertAfter Analogous to I =item * Remove Removes the specified entries from the path. =item * Replace Takes a /pattern/ and a list. Traverses the path and replaces all entries which match the pattern with the concatenated list entries. =item * ListNonexistent Returns a list of all entries which do not exist as filesystem entities. =item * DeleteNonexistent Removes from the path all entries which do not exist as filesystem entities. =item * Uniqify Removes redundant entries (the 2nd through nth instances of each entry). =item * Whence Takes a pattern and returns an ordered list of all filenames found along the path which match it and are executable. =item * Shell Returns a string suitable for passing to a shell which would set and export the pathvar to its current value within the shell context. =back =head1 NOTES =over 4 =item * No provision is made for path variables which are not also environment variables, a situation which is technically possible but quite rare. =item * Except where necessary no assumption is made that path entries should be directories, because pathvars like CLASSPATH may contain "virtual dirs" such as zip/jar files. For instance the I method does not remove entries which are files. In Perl terms the test applied is C<-e>, not C<-d>. =item * The shorthand notation for pathvar I is implemented by hacking I<@FOO::ISA>, so there's a slight risk of namespace collision if your code also creates packages with all-upper-case names. No packages are created unless the shorthand notation is employed. =item * There's some cute code in the Env module by Gregor N. Purdy for splitting pathvars into arrays using ties. I'd love to be able to take advantage of that, and it pains me to do the same thing (and not as well) here rather than using Env. Unfortunately it's a newish feature (5.6.0? 5.005? 5.6.1?) in Env and I don't want Env::Path to be "tied" to the very latest Perls. =back =head1 WORKS ON UNIX and Windows. =head1 AUTHOR David Boyce =head1 COPYRIGHT Copyright (c) 2000-2001 David Boyce. All rights reserved. This Perl program is free software; you may redistribute and/or modify it under the same terms as Perl itself. =head1 SEE ALSO perl(1), perlobj(1), Env::Array(3), Env(3) =cut