From a276db189a656a4cc5881a2ebc4cad3113685030 Mon Sep 17 00:00:00 2001 From: Lorry Tar Creator Date: Tue, 21 Jul 2015 13:23:57 +0000 Subject: File-Which-1.19 --- lib/File/Which.pm | 335 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 335 insertions(+) create mode 100644 lib/File/Which.pm (limited to 'lib/File') diff --git a/lib/File/Which.pm b/lib/File/Which.pm new file mode 100644 index 0000000..d9edb7c --- /dev/null +++ b/lib/File/Which.pm @@ -0,0 +1,335 @@ +package File::Which; + +use strict; +use warnings; +use Exporter (); +use File::Spec (); + +# ABSTRACT: Perl implementation of the which utility as an API +our $VERSION = '1.19'; # VERSION + + +our @ISA = 'Exporter'; +our @EXPORT = 'which'; +our @EXPORT_OK = 'where'; + +use constant IS_VMS => ($^O eq 'VMS'); +use constant IS_MAC => ($^O eq 'MacOS'); +use constant IS_DOS => ($^O eq 'MSWin32' or $^O eq 'dos' or $^O eq 'os2'); +use constant IS_CYG => ($^O eq 'cygwin'); + +# For Win32 systems, stores the extensions used for +# executable files +# For others, the empty string is used +# because 'perl' . '' eq 'perl' => easier +my @PATHEXT = (''); +if ( IS_DOS ) { + # WinNT. PATHEXT might be set on Cygwin, but not used. + if ( $ENV{PATHEXT} ) { + push @PATHEXT, split ';', $ENV{PATHEXT}; + } else { + # Win9X or other: doesn't have PATHEXT, so needs hardcoded. + push @PATHEXT, qw{.com .exe .bat}; + } +} elsif ( IS_VMS ) { + push @PATHEXT, qw{.exe .com}; +} elsif ( IS_CYG ) { + # See this for more info + # http://cygwin.com/cygwin-ug-net/using-specialnames.html#pathnames-exe + push @PATHEXT, qw{.exe .com}; +} + + +sub which { + my ($exec) = @_; + + return undef unless $exec; + + my $all = wantarray; + my @results = (); + + # check for aliases first + if ( IS_VMS ) { + my $symbol = `SHOW SYMBOL $exec`; + chomp($symbol); + unless ( $? ) { + return $symbol unless $all; + push @results, $symbol; + } + } + if ( IS_MAC ) { + my @aliases = split /\,/, $ENV{Aliases}; + foreach my $alias ( @aliases ) { + # This has not been tested!! + # PPT which says MPW-Perl cannot resolve `Alias $alias`, + # let's just hope it's fixed + if ( lc($alias) eq lc($exec) ) { + chomp(my $file = `Alias $alias`); + last unless $file; # if it failed, just go on the normal way + return $file unless $all; + push @results, $file; + # we can stop this loop as if it finds more aliases matching, + # it'll just be the same result anyway + last; + } + } + } + + return $exec + if !IS_VMS and !IS_MAC and !IS_DOS and $exec =~ /\// and -f $exec and -x $exec; + + my @path = File::Spec->path; + if ( IS_DOS or IS_VMS or IS_MAC ) { + unshift @path, File::Spec->curdir; + } + + foreach my $base ( map { File::Spec->catfile($_, $exec) } @path ) { + for my $ext ( @PATHEXT ) { + my $file = $base.$ext; + + # We don't want dirs (as they are -x) + next if -d $file; + + if ( + # Executable, normal case + -x _ + or ( + # MacOS doesn't mark as executable so we check -e + IS_MAC + || + ( + ( IS_DOS or IS_CYG ) + and + grep { + $file =~ /$_\z/i + } @PATHEXT[1..$#PATHEXT] + ) + # DOSish systems don't pass -x on + # non-exe/bat/com files. so we check -e. + # However, we don't want to pass -e on files + # that aren't in PATHEXT, like README. + and -e _ + ) + ) { + return $file unless $all; + push @results, $file; + } + } + } + + if ( $all ) { + return @results; + } else { + return undef; + } +} + + +sub where { + # force wantarray + my @res = which($_[0]); + return @res; +} + +1; + +__END__ + +=pod + +=encoding UTF-8 + +=head1 NAME + +File::Which - Perl implementation of the which utility as an API + +=head1 VERSION + +version 1.19 + +=head1 SYNOPSIS + + use File::Which; # exports which() + use File::Which qw(which where); # exports which() and where() + + my $exe_path = which 'perldoc'; + + my @paths = where 'perl'; + # Or + my @paths = which 'perl'; # an array forces search for all of them + +=head1 DESCRIPTION + +L finds the full or relative paths to executable programs on +the system. This is normally the function of C utility. C is +typically implemented as either a program or a built in shell command. On +some platforms, such as Microsoft Windows it is not provided as part of the +core operating system. This module provides a consistent API to this +functionality regardless of the underlying platform. + +The focus of this module is correctness and portability. As a consequence +platforms where the current directory is implicitly part of the search path +such as Microsoft Windows will find executables in the current directory, +whereas on platforms such as UNIX where this is not the case executables +in the current directory will only be found if the current directory is +explicitly added to the path. + +If you need a portable C on the command line in an environment that +does not provide it, install L which provides a command line +interface to this API. + +=head2 Implementations + +L searches the directories of the user's C (the current +implementation uses L to determine the correct C), +looking for executable files having the name specified as a parameter to +L. Under Win32 systems, which do not have a notion of directly +executable files, but uses special extensions such as C<.exe> and C<.bat> +to identify them, C takes extra steps to assure that +you will find the correct file (so for example, you might be searching for +C, it'll try F, F, etc.) + +=head3 Linux, *BSD and other UNIXes + +There should not be any surprises here. The current directory will not be +searched unless it is explicitly added to the path. + +=head3 Modern Windows (including NT, XP, Vista, 7, 8, 10 etc) + +Windows NT has a special environment variable called C, which is used +by the shell to look for executable files. Usually, it will contain a list in +the form C<.EXE;.BAT;.COM;.JS;.VBS> etc. If C finds such an +environment variable, it parses the list and uses it as the different +extensions. + +=head3 Cygwin + +Cygwin provides a Unix-like environment for Microsoft Windows users. In most +ways it works like other Unix and Unix-like environments, but in a few key +aspects it works like Windows. As with other Unix environments, the current +directory is not included in the search unless it is explicitly included in +the search path. Like on Windows, files with C<.EXE> or <.BAT> extensions will +be discovered even if they are not part of the query. C<.COM> or extensions +specified using the C environment variable will NOT be discovered +without the fully qualified name, however. + +=head3 Windows 95, 98, ME, MS-DOS, OS/2 + +This set of operating systems don't have the C variable, and usually +you will find executable files there with the extensions C<.exe>, C<.bat> and +(less likely) C<.com>. C uses this hardcoded list if it's running +under Win32 but does not find a C variable. + +As of 2015 none of these platforms are tested frequently (or perhaps ever), +but the current maintainer is determined not to intentionally remove support +for older operating systems. + +=head3 VMS + +Same case as Windows 9x: uses C<.exe> and C<.com> (in that order). + +As of 2015 the current maintainer does not test on VMS, and is in fact not +certain it has ever been tested on VMS. If this platform is important to you +and you can help me verify and or support it on that platform please contact +me. + +=head1 FUNCTIONS + +=head2 which + + my $path = which $short_exe_name; + my @paths = which $short_exe_name; + +Exported by default. + +C<$short_exe_name> is the name used in the shell to call the program (for +example, C). + +If it finds an executable with the name you specified, C will return +the absolute path leading to this executable (for example, F or +F). + +If it does I find the executable, it returns C. + +If C is called in list context, it will return I the +matches. + +=head2 where + + my @paths = where $short_exe_name; + +Not exported by default. + +Same as L in array context. Same as the +C utility, will return an array containing all the path names +matching C<$short_exe_name>. + +=head1 CAVEATS + +This module has no non-core requirements for Perl 5.6.2 and better. + +This module is fully supported back to Perl 5.8.1. It may work on 5.8.0. +It should work on Perl 5.6.x and I may even test on 5.6.2. I will accept +patches to maintain compatibility for such older Perls, but you may +need to fix it on 5.6.x / 5.8.0 and send me a patch. + +Not tested on VMS although there is platform specific code +for those. Anyone who haves a second would be very kind to send me a +report of how it went. + +=head1 SUPPORT + +Bugs should be reported via the GitHub issue tracker + +L + +For other issues, contact the maintainer. + +=head1 SEE ALSO + +=over 4 + +=item L, L + +Command line interface to this module. + +=item L + +Comes with a C function with slightly different semantics that +the traditional UNIX where. It will find executables in the current +directory, even though the current directory is not searched for by +default on Unix. + +=item L + +This module purports to "check that a command is available", but does not +provide any documentation on how you might use it. + +=back + +=head1 AUTHORS + +=over 4 + +=item * + +Per Einar Ellefsen + +=item * + +Adam Kennedy + +=item * + +Graham Ollis + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 2002 by Per Einar Ellefsen . + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut -- cgit v1.2.1