Windows TIPS
[Scripting]
  Windows TIPS TOPへ
Windows TIPS全リストへ
内容別分類一覧へ

whichコマンドを作る

―― for制御変数の拡張表記方法について ――

 

デジタルアドバンテージ
2003/07/26
 
対象OS
Windows 2000 Professional
Windows 2000 Server
Windows 2000 Advanced Server
Windows XP Home Edition
Windows XP Professional
Windows Server 2003
forコマンドの制御変数の参照方法にはさまざまな拡張表記が用意されている。
「%~$PATH:I」という表記方法を使うと、PATH変数の指すフォルダからファイルを検索させることができる。これを使ってwhichコマンドを実現してみる。
 
解説

 UNIXやLinux OSには、whichというコマンドがある。引数にコマンド名を与えると、そのコマンドが置かれている場所を表示するというコマンドである。ユーザーがあるコマンドを実行しようとすると、シェル(Windowsでいうところのコマンド・プロンプトのようなのもの)は環境変数PATHの指しているフォルダを順番に検索し(PATHには、複数のフォルダ名が「:」記号で区切られてセットされている)、最初に見付かったファイルを実行する。システムに同じ名前のコマンドが複数インストールされている場合、実行パスがたくさんある場合に、どこのフォルダにあるコマンド(実行ファイル)が実際に呼び出されているかを簡単に調べることができる。

※UNIXにおけるwhichコマンドの使用例

$ echo $PATH …現在のPATH変数の内容を表示させる
/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/sbin:/usr/sbin:
/home/hiroy-u/bin
$ which nslookup …nslookupコマンドの場所を調べる
/usr/bin/nslookup …/usr/binフォルダにあった!

 Windows OSのコマンド・プロンプトでは、UNIXと同じ機能を持つコマンドがいくつも用意されているが、なぜかこのwhichに相当するコマンドは用意されていない。そこでバッチ・コマンドを使って非常に簡略化したwhichコマンドを実現してみよう。以下の2行の内容を持つファイルを作成し、which.batというファイル名で保存すればよい。保存先は、Windows OSのシステム・フォルダ(Windows NTならC:\WINNT、Windows 2000以降ならC:\WINDOWSなど)でよいだろう。

@echo off
for %%I in (%1 %1.com %1.exe %1.bat %1.cmd %1.vbs %1.js %1.wsf) do if exist %%~$path:I echo %%~$path:I

※この2行の内容をファイルwhich.batとして保存すること

 実行するには、whichに続けて、調べたいコマンドの名前を付ければよい。

C:\>which notepad …メモ帳アプリケーション(notepad.exe)の場所を調べる
D:\WINNT\system32\notepad.exe …D:\WINNT\SYSTEM32に置かれているのが分かる
C:\>which su …su.exeというコマンドを探してみる
D:\Program Files\Resource Kit\su.exe …リソースキットのツールであった

 which.batで行っている内容は非常に簡単である。引数として与えられた文字列に、「.com」や「.exe」「.bat」などを付加し、それがPATH環境変数の指す各フォルダ内に存在しているかどうかを調べているだけである。ただし本来のUNIX上のwhichコマンドと比較すると、実行ファイルしか検索できないとか(UNIXの場合は、シェルのエイリアス・コマンドなどを識別して表示する)、フォルダの検索順序が異なるなど、いくつか異なる点がある。

 Windows OSがコマンドを検索する場合、PATH環境変数の先頭からフォルダ名を1つずつ取り出し、そのフォルダ内に.comや.exe、.batファイルなどがあるかどうかを調べ、なければ次のフォルダを検索する。しかしこのwhichでは、まず.comファイルがPATH環境変数の指すフォルダ内にあるかどうかを調べ、次に.exeを調べ、……といったように検索を実行している。そのため、実際に実行されるコマンドとは異なるファイルが表示されたり、単なるフォルダ名がマッチしてしまったりこともある。また、コマンド・プロンプト上で直接実行ファイル名を入力する場合と、startコマンドの引数としてファイル名を与えたり、[ファイル名を指定して実行]で指定する場合とでは結果が異なるが(例:Windows XPのコマンド・プロンプト上で直接「msconfig」と入力しても何も実行されないが、「start msconfig」とすると「システム構成ユーティリティ」が起動される)、それらについても対応していない。そのあたりは各自で改良していただきたい。

 なおfor文のリストの先頭で、(拡張子を指定しない)自分自身と一致するかどうかを検出しているが(先頭の「%1」のこと)、これは例えば「which diskmgmt.msc」などという利用方法を想定している。コマンド・プロンプト上や、[ファイル名を指定して実行]において、直接「diskmgmt.msc」と入力すると「ディスクの管理」ツールが起動されるが、このような実行ファイル以外を直接指定して起動する場合もあるので、それらにマッチさせるためにこのような対策を施している。

環境変数とファイル検索

 このコマンドの一番肝心な部分は、「%%~$path:I」という表記方法にある。それ以外のforとかif、echoコマンドは、Windows 9xの時代から使われている、非常に基本的な表記方法なので、特に解説はしない。

 「%%~$path:I」は、環境変数PATH(小文字のpathでも同じ)の指している各フォルダ中に、変数I(バッチ・ファイル中で表記する場合は「%%I」とし、単にコマンド・プロンプト中で直接利用する場合は「%I」と表記する)の指すファイル名が存在するかどうかを調べ、存在すればそのフルパス名を返し(最初に一致したもののみ返す)、そうでなければ空文字列を返すという意味である。これはforコマンド中でのみ利用可能な特殊な表記であり、ほかにも以下のような特別な表記方法が用意されている。

表記 意味
%~I パス中に含まれるすべての引用符(「"」記号)を削除して展開する。
%~fI %Iをフルパス名に展開する
%~dI %Iからドライブ文字だけを取り出す
%~pI %Iからパス名部分だけを取り出す
%~nI %Iから(パス名部分を取り除いて)最後のファイル名部分だけを取り出す
%~xI %Iからファイルの拡張子部分だけを取り出す
%~sI 展開されたパスを、8.3形式の短い名前だけに変換する
%~aI ファイルの属性リストに変換する
%~tI ファイルの最終更新日付と時刻のリストに展開する
%~zI ファイルのサイズ(byte単位で数える)に展開する
%~$PATH:I PATH環境変数(PATH以外の環境変数でもよい)に指定されているフォルダのリストを順番に検索し、最初に見つかった%Iというファイルのフルパス名に展開する。見つからない場合は空文字列になる
forコマンドにおける制御変数の特殊な表記方法
forコマンドの実行文を指定する場所(do以降の部分)では、forの制御変数(ここでは「%I」としている)に対して、このような特殊な表記方法をいくつか利用することができる。

 今回のwhich.batというコマンドでは、これらの表記方法のうち、最後の表記方法を使って、PATH環境変数(フォルダ名の一覧を「;」で区切って並べたリストなら、PATH以外の環境変数でもよい)から、該当する実行ファイルを検索している。

 より進んだforコマンドの使い方については、別稿の「Windows 2000 コマンドライン徹底活用―第7回 forコマンド」などを参照していただきたい。End of Article

この記事と関連性の高い別の記事

このリストは、デジタルアドバンテージが開発した自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。

generated byJigsaw
「Windows TIPS」


Windows Server Insider フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Windows Server Insider 記事ランキング

本日 月間