dos の which

MS-DOS というか,MS Windows の Command Prompt で,というか,そこで動作する簡易版のwhichを作った.doswhichという名前にした.
簡易版だというのは,DOSのばあい,どの拡張子が優先されるかというようなルールがあったはずだが,そんな面倒なのは無視する,という乱暴な仕様なので.始めに見つかったものまたは見つかったもの全部(-aを付けた時)を報告する.拡張子がコマンド用でなくても気にしない.

08.03.21追記: 拡張子は,どうも,PATHEXTなる環境変数をみるらしい,という話を聞いたので,そのように修正してみた.-aは相変わらず有効だが,こちらも,PATHEXTで指定されているもののみを報告する.PATHEXTが未定義の時にどうなるべきかは良くわからないので,いい加減に書いた.

doswhich.bat

@echo off
perl %HOME%\bin\doswhich.pl %1 %2 %3 %4 %5 %6 %7 %8 %9

doswhich.pl

use Getopt::Std;

sub usage {
  die "Usage: doswhich [-a] commandname\n";
}

our $opt_a;
getopts('a') or usage();

@ARGV == 1 or usage();
my $name = $ARGV[0];

$_ = $ENV{PATHEXT};
my @ext = defined($_) ? split(/\;/) : qw(.com .exe .bat .cmd);
my $sPat = '^' . $name . '(' . join('|', map( "\\" . $_ , @ext )) . ')$';
my $pattern = qr{$sPat}i;

my @dirs = split(/\;/, $ENV{PATH});
unshift (@dirs, ".");
MAINLOOP: foreach my $dir (@dirs) {
  opendir(D, $dir) or next;
  while (defined(my $f = readdir(D))) {
    if ($f =~ /$pattern/) {
      print "$dir\\$f\n";
      last MAINLOOP unless $opt_a;
    }
  }
  closedir(D);
}