• ベストアンサー

実行ファイルのパスを取得したい

C言語で自分自身がどのディレクトリに存在しているか 知りたいのです。 簡単に例を挙げて説明します。 UNIX C言語で cmd1 という実行ファイルを作成しました。 環境変数は以下のように定義されていたとします。 PATH=/bin:/usr/bin /binにcmd1を配置してカレントディレクトリ/homeにおいて cmd1を実行、cmd1プログラム内で"/bin/cmd1" を取得したいのです。 続けて、/bin/cmd1を/usr/bin/cmd1移動して、cmd1を実行すれば、 プログラム内で"/usr/bin/cmd1"を取得できるコーディングをしたいのです。 typeコマンドのような事をC言語で行いたいのですが。 お分かりの方いらっしゃいましたら教えてください。 よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.7

>C:\WINDOWS\COMMAND\CMD1.EXE >と表示されます。 >この違いはなんだろう? C:\windows\commandってフォルダに突っ込んでる時点でOSがぜんぜん違いますよね。 Win9xとNT系じゃ。 9x系はフルパスが、NT系は起動時の実行コマンドargv[0]には格納されています。 UNIXでは実行モジュールのフルパスを取得する一般的な方法は無いみたいです。 Windowsでは#4の方の書かれているとおり、GetModuleFileName()です。

yukooo
質問者

お礼

「UNIXでは実行モジュールのフルパスを取得する一般的な方法は無いみたいです」 そうですか。 こちらに質問を書き込む前に私なりに調べてみました。 もしかして出来ないのかなぁ?と少し思いつつ、 そんなはずはないだろう。。。と思い質問した次第です。 回答ありがとうございました。

その他の回答 (7)

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.8

うろ覚えの記憶で申し訳ありませんが、TclのAPIであるTcl_FindExecutable関数がプログラムのフルパスを取得できます。 Tclを使えるのであれば、そのまま使っても構いませんし、Tcl_FindExecutable関数を真似て、自作してもよいかと思います。 大まかに言って、次のような方法で実現されていたはずです。 gccでは、コマンドラインで入力されたプログラム名が、そのままargv[0]に格納されます。argv[0]に絶対パスまたは相対パスが指定されていれば(要するに'/'が含まれている場合)、そのディレクトリを元にフルパスを生成します。ファイル名のみ指定されていれば、環境変数PATHに指定されているディレクトリを順に検索して、該当するプログラムが存在するかどうかを調べます。 プログラム起動後に、ファイルが削除されたり、移動されたり、改名される可能性もあるので、100%確実な方法とは言えないでしょうが、普通は問題ないかと思います。高いセキュリティが要求される場合は、やめた方がよいかも知れませんが...

yukooo
質問者

お礼

やはり行き着く先はPATHのディレクトリ探索になりますか。 おしゃられるように起動後のファイル移動等に注意が必要ですね。 回答ありがとうございました。

  • nitscape
  • ベストアンサー率30% (275/909)
回答No.6

#4です。 この掲示板では討論のような個人的なやりとりは禁止されているので書き込むのは悩むところですが、質問者さんが誤解するといけないので... 繰り返しになりますがargやWindowsAPIのGetCommandLineで取得できるのは実行時の「コマンド」になります。そのため実行ファイルに対するフルパスではありません。 しかしargを調べて見ると実行時にフルパスが取得できていることがあります。それは実行時にフルパスを指定して起動した場合です。また実行するときにフルパスを指定していないにもかかわらずフルパスが返ることもあります。これはWindowsAPIのCreateProcessが勝手にフルパスに変換することがあるためです。 具体的にはWindows9x系ではフルパスが返ることが多いようです。WindowsNT4.0/2000/XPの場合はフルパスにならないことが多いです。 また質問は >C言語で自分自身がどのディレクトリに存在しているか ということです。自分自身がどのディレクトリに存在しているかを知るためには自分自身ファイルへのフルパス(例c:\a.exe)を取得して、そこからファイルの部分を除去してディレクトリ(例c:\)に変換します。 しかしargなどで取得できるのは"実行ファイル"のみです。例えば自分自身がDLLファイルなどで実行されていた場合にはDLLをロードしているExeのフルパスが返るだけであり、自分自身へのフルパスを取得することができません。 そのためWindowsでは自分自身のフルパスを取得するにはGetModuleFileNameのようなAPIを利用します。 EXEであれば #include "windows.h" TCHAR pszPath[MAX_PATH]; GetModuleFileName(NULL,pszPath,MAX_PATH); のように利用します。DLLの場合は第一引数をモジュールへのハンドルにします。 UNIXでは。。。すみません。知識がなく分かりません。 argを見てフルパスならそれを利用、そうでなければカレントフォルダを参照する、のような方法が考えられますが、「./aaa/bbb/cmd.exe」のような相対的なパスを示すargが返ってくることも考えられるので気をつける必要があると思います。

yukooo
質問者

お礼

回答ありがとうございます。 「Windows9x系ではフルパスが返ることが多いようです。WindowsNT4.0/2000/XPの場合はフルパスにならないことが多いです」 そうなんだ。と驚いています。 GetModuleFileNameについても丁寧に書いていただきありがとうございます。

  • ty_cobb
  • ベストアンサー率16% (1/6)
回答No.5

>#4殿 話をドリフトさせるのはやめてください。 >Windowsで自分自身のファイルを取得したい場合はGetModuleFileNameを使います。 そんな要求はしていません。 >コマンドプロンプトなどで実行した場合はフルパスになりません。 試したんですか? こちらは書いたとおりのことを試してみて、書き込んでるんですよ。c:\windows\commandに実際にcmd1.exeをコピーし、コマンドプロンプトからc:\へ移動してcmd1とタイプしてごらんなさい。 C:\WINDOWS\COMMAND\CMD1.EXE と表示されますよ。

yukooo
質問者

お礼

回答ありがとうございます。 確かにGetModuleFileNameは期待している回答では ありません。 ですが、UNIXでという質問の意図とは異なりはしますが、 WindowsでもOS違いでargv[0]の値は異なるみたい。 というのは驚きと面白い発見でした。

  • nitscape
  • ベストアンサー率30% (275/909)
回答No.4

argやGetCommandLineは実行時に渡された「コマンド」が返ります。VC++などでは実行時にフルパスで実行するためargでフルパスが返りますが、コマンドプロンプトなどで実行した場合はフルパスになりません。プラットフォームが何なのかにもよりますが、Windowsで自分自身のファイルを取得したい場合はGetModuleFileNameを使います。

yukooo
質問者

お礼

回答ありがとうございます。 VC++で実行した場合とコマンドプロンプトから 実行、さらにプラットフォームの違いによっても argv[0]の値が異なる可能性があるということですね。 勉強になります。

  • ty_cobb
  • ベストアンサー率16% (1/6)
回答No.3

こちらも実際に試してみました。 VC++6.0で、console applicationを作って、cmd1.exeを作成し、c:\windows\commandに入れました。 c:\上から、cmd1とタイプすると、 C:\WINDOWS\COMMAND\CMD1.EXE と表示されます。 この違いはなんだろう? ていうか、argv[0]にフルパスが含まれるのは大分昔からの仕様だと思ってたんだけど・・・。

yukooo
質問者

お礼

WindowsのOS違いで動作が異なるということなんですね。 いろいろ試して頂きありがとうございます。

  • ty_cobb
  • ベストアンサー率16% (1/6)
回答No.2

今unixの環境が手元に無いんだけど、MS-DOSで実行すると argv[0]はフルパスを返します。 "c:\windows\デスクトップ\cmd1.exe"のように。 unixでは"/usr/bin/cmd1"を返さないのでしょうか? "cmd1"のみ?

yukooo
質問者

補足

回答ありがとうございます。 MS-DOSはあまり経験がないのですが今やってみました。 Windows2000です。 cmd1.exeを作成して、PATHの通った場所にコピーしました。 具体的にはC:\WINNT\system32に入れました。 そしてカレントをC:\に移動して実行しました。 C:\>cmd1.exe cmd1.exe cmd1.exeとしか表示されませんでした。 私の説明がまだ不足しているような気がします。 C:\WINNT\system32\cmd1.exe というパスを何らかの方法で簡単に取得できないかと 苦慮しています。 よろしくお願いします。

  • ty_cobb
  • ベストアンサー率16% (1/6)
回答No.1

#include <stdio.h> int main(int argc,char **argv) { printf("%s\n",argv[0]); return 0; }

yukooo
質問者

補足

申訳ありません。説明が不足していたようです。 カレントディレクトリでは、cmd1 としか入力しません。 よろしくお願いします。

関連するQ&A

  • phpの実行ファイル位置の取得

    フルパス指定で実行したPHPのディレクトリを取得する事は可能でしょうか。 実行中にそのディレクトリにカレントディレクトリを移動させ、さらに処理を進めていきたいのですが、phpファイルの位置が取得できません。 /home/user/xxxxx/yyyyy/zzzzz/aaa.php ↑をどこの場所で実行しても実行中に /home/user/xxxxx/yyyyy/zzzzz/の位置を取得でき、相対パスでyyyyyにあるファイルを読み込みたいのです。 実行したファイルの位置を取得する事ってできますでしょうか。

    • ベストアンサー
    • PHP
  • 環境変数pathについて

    環境変数pathについてお聞きしたいことがあります。たとえば /usr/local/bin:/bin:/usr/bin: このような場合、/usr/local/binと/binと/usr/binに入力されたコマンドのプログラム ファイルを探しに行くというような解釈をしているのですが、 /usr/local/binがあるならば/binや/usr/binといったようなpathは必要ないような気がします。なぜこのような書き方をするのでしょうか? お忙しいところ申し訳ございませんがよろしくお願いします。

  • パスを通したはずなのに「パスは見つかりません」

    お世話になります。始めてプログラミングを勉強しています。 環境はWindws XPHome Edition Ver2002、SP2 コンパイラとしてダウンロードしたのは、 「Borland C++compiler」です。 インストールして、pathの環境変数の最後にbin;c:\Borland\Bcc55\binと付けました。 もとの環境変数↓ (%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;C:\Program Files\Common Files\GTK\2.0 )  実際コマンドラインでメモ帳を開こうと>C:\WINDWS\NOTEPAD.EXEと打ち込んでも、 指定されたパスは見付かりませんとでます。 確かにCドライブの「WINDWS」フォルダの中にNOTEPAD.EXEは存在します。 他にもカレントディレクトリを変えようとして、>cd ○○と打っても、 確かにあるはずなのに「指定されたパスはみつかりません」になってしまいます。 打ち込んだ文字や環境変数に加えた文字に間違いはないかと、かなり確認したり似たような質問を検索してみたのですが、どうも分からずお手上げ状態です。 よろしければ教えていただけないでしょうか。 ちなみに「10日でおぼえるC言語」というテキストどおりにやっています。

  • eclipseでC言語がコンパイルできない

    cigwinを先日入れてeclipseでC言語開発をしようと思ったんですが、 Hello Worldを実行しようとすると、 ・Program "g++" not found in PATH ・Program "gcc" not found in PATH というエラーがでます。 gcc,g++がPATHにないよ、といっているようですが、 これはどのように解決したらいいのでしょうか? cigwinでgcc,g++の場所を確認すると/usr/bin/gcc, /usr/bin/g++とありました。 インストールはされているようです。 環境変数の方もシステム環境変数、ユーザ環境変数両方に、 C:\cygwin\bin;C:\cygwin\usr\bin;C:\cygwin\usr\local\bin と指定しています。 何かPATHの設定を間違っているのでしょうか? それともeclipseの設定でしょうか?

  • 実行ファイルのパスの取得

    現在実行ディレクトリはAです。 また実行ファイルはtest.plでこれらは /A/B/test.pl という関係になっています。 test.plでこのようなパスを取得するにはどのようにしたら良いでしょうか? お分かりの方どうぞ教えてください。

    • ベストアンサー
    • Perl
  • WindowsでPATHにあるコマンドを補完?

    お世話になります。 Windowsのコマンドラインプロンプトでは、ある程度タイプして[TAB}キーを押下すると、カレントディレクトリにあるファイル名を補完してくれます。 たとえば xxxxYYY というファイルがあるディレクトリにおいて  C:\foo\> x[TAB] のようにタイプすると、xxxxYYYと補完されます。 LinuxやMacを含むUNIX系のコマンドライン環境では、カレントディレクトリだけでなく、PATHに入っているコマンドも補完してくれます。具体的に言うと、C:\myProgram\bin\xxxxYYY.exeというコマンドを、C:\fooという全然違うカレントディレクトリにあっても、  C:\foo\> x[TAB] で補完してくれます。 この、PATHにあるコマンド名の補完は、Windowsでも可能でしょうが。 具体的には、何らかのフリーウェアを常駐させる、レジストリを書き換えるなどによって、可能になるでしょうか。 私は20年以上DOS/Windowsを使い込んでいるのですが、この機能さえあれば本当に助かります。 Linuxを使え、WindowsでCygwinを使えというのはナシで、あくまでWindowsのcmdを使い続けるという前提でお願いします。 よろしくお願いいたします。

  • シェルスクリプトでの絶対パスの取得

    UNIXのシェルスクリプトで、引数として渡された相対パスから絶対パスを取得するには、そうすればよいでしょうか。 cd 相対パス 変数=`pwd` これが一番普通のやり方でしょうか。 change directory しなくてもできる方法がないのかなあと思ったもので。

  • パス(PATH)の設定ファイルについて

    OSはRed Hat Linux 9 を使用しております。 また、シェルはbashを使用しております。 ユーザがシステムにログインする際は、通常ですと /etc/profile ~/.bash_profile ~/.bash_login ~/.profile ファイルを読込、パス(PATH)の設定を行うと思いますが、 sshでrootユーザでシステムにログインした際は、 「echo $PATH」の結果は以下でした。 /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin:/sbin su -で再度rootユーザでログインした際、もしくは、他ユーザからsu -でログインすると 「echo $PATH」の結果は以下でした。 /bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/usr/bin/X11:/usr/X11R6/bin:/root/bin:/sbin ログインの仕方でパス(PATH)に違いがあります。 また、「/usr/local/bin」をパス(PATH)として設定している記述が 上記ファイルに見当たりません。 http://sakaguch.com/PastBBS/0038/B0018808.html http://oshiete1.goo.ne.jp/kotaeru.php3?q=800405 等のサイトを参考に、以下ディレクトリ配下を確認しましても /etc/profile.d /etc/rc.d/init.d /etc/rc.d/rc3.d 「/usr/local/bin」をパス(PATH)として設定している記述が 見当たりません。 ログインの仕方でパス(PATH)に何故違いがあるのか、 また「/usr/local/bin」をパス(PATH)として設定している記述がある ファイルをご存知の方ご教授頂きたく思います。 宜しくお願いします。

  • shシェルで実行パスではなくファイルのパスを取得する方法

    pwdコマンドで、実行パスを取得する事は可能ですが、このパスはどこから呼び出されたかによって変化します。 そうではなく、どこから呼ばれても、そのSHファイルのパスを取得する方法を教えてください。 <例:ディレクトリ> dir_a/ | +-dir_b/ | +-pgm_a.sh <例:シェル> ##### pgm_a.sh ##### #!/bin/sh echo `pwd` ##### pgm_a.sh ##### <例:コマンド> > pwd dir_a > ./dir_b/pgm_a.sh dir_a > cd ./dir_b > ./pgm_a.sh dir_a/dir_b どこから呼ばれても、常にpgm_a.shのパスである。 「dir_a/dir_b/」を取得できるコマンドが知りたいです。 あるいはシステム変数のようなものでも構いません。 よろしくお願いします。

  • 自身のパスの取得

    レンタルサイトでPHPを使っているのでディレクトリのフルパスが分からないのですが、このPHPファイル自身のディレクトリを得る関数はありませんか? http://www...ではなく、/usr/local/..のようなディレクトリのパスを取得する関数を教えてください。

    • ベストアンサー
    • PHP

専門家に質問してみよう