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言語で行いたいのですが。
お分かりの方いらっしゃいましたら教えてください。
よろしくお願いします。
No.7ベストアンサー
- 回答日時:
>C:\WINDOWS\COMMAND\CMD1.EXE
>と表示されます。
>この違いはなんだろう?
C:\windows\commandってフォルダに突っ込んでる時点でOSがぜんぜん違いますよね。
Win9xとNT系じゃ。
9x系はフルパスが、NT系は起動時の実行コマンドargv[0]には格納されています。
UNIXでは実行モジュールのフルパスを取得する一般的な方法は無いみたいです。
Windowsでは#4の方の書かれているとおり、GetModuleFileName()です。
「UNIXでは実行モジュールのフルパスを取得する一般的な方法は無いみたいです」
そうですか。
こちらに質問を書き込む前に私なりに調べてみました。
もしかして出来ないのかなぁ?と少し思いつつ、
そんなはずはないだろう。。。と思い質問した次第です。
回答ありがとうございました。
No.8
- 回答日時:
うろ覚えの記憶で申し訳ありませんが、TclのAPIであるTcl_FindExecutable関数がプログラムのフルパスを取得できます。
Tclを使えるのであれば、そのまま使っても構いませんし、Tcl_FindExecutable関数を真似て、自作してもよいかと思います。
大まかに言って、次のような方法で実現されていたはずです。
gccでは、コマンドラインで入力されたプログラム名が、そのままargv[0]に格納されます。argv[0]に絶対パスまたは相対パスが指定されていれば(要するに'/'が含まれている場合)、そのディレクトリを元にフルパスを生成します。ファイル名のみ指定されていれば、環境変数PATHに指定されているディレクトリを順に検索して、該当するプログラムが存在するかどうかを調べます。
プログラム起動後に、ファイルが削除されたり、移動されたり、改名される可能性もあるので、100%確実な方法とは言えないでしょうが、普通は問題ないかと思います。高いセキュリティが要求される場合は、やめた方がよいかも知れませんが...
やはり行き着く先はPATHのディレクトリ探索になりますか。
おしゃられるように起動後のファイル移動等に注意が必要ですね。
回答ありがとうございました。
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"
TCHARpszPath[MAX_PATH];
GetModuleFileName(NULL,pszPath,MAX_PATH);
のように利用します。DLLの場合は第一引数をモジュールへのハンドルにします。
UNIXでは。。。すみません。知識がなく分かりません。
argを見てフルパスならそれを利用、そうでなければカレントフォルダを参照する、のような方法が考えられますが、「./aaa/bbb/cmd.exe」のような相対的なパスを示すargが返ってくることも考えられるので気をつける必要があると思います。
回答ありがとうございます。
「Windows9x系ではフルパスが返ることが多いようです。WindowsNT4.0/2000/XPの場合はフルパスにならないことが多いです」
そうなんだ。と驚いています。
GetModuleFileNameについても丁寧に書いていただきありがとうございます。
No.5
- 回答日時:
>#4殿
話をドリフトさせるのはやめてください。
>Windowsで自分自身のファイルを取得したい場合はGetModuleFileNameを使います。
そんな要求はしていません。
>コマンドプロンプトなどで実行した場合はフルパスになりません。
試したんですか?
こちらは書いたとおりのことを試してみて、書き込んでるんですよ。c:\windows\commandに実際にcmd1.exeをコピーし、コマンドプロンプトからc:\へ移動してcmd1とタイプしてごらんなさい。
C:\WINDOWS\COMMAND\CMD1.EXE
と表示されますよ。
回答ありがとうございます。
確かにGetModuleFileNameは期待している回答では
ありません。
ですが、UNIXでという質問の意図とは異なりはしますが、
WindowsでもOS違いでargv[0]の値は異なるみたい。
というのは驚きと面白い発見でした。
No.4
- 回答日時:
argやGetCommandLineは実行時に渡された「コマンド」が返ります。
VC++などでは実行時にフルパスで実行するためargでフルパスが返りますが、コマンドプロンプトなどで実行した場合はフルパスになりません。プラットフォームが何なのかにもよりますが、Windowsで自分自身のファイルを取得したい場合はGetModuleFileNameを使います。回答ありがとうございます。
VC++で実行した場合とコマンドプロンプトから
実行、さらにプラットフォームの違いによっても
argv[0]の値が異なる可能性があるということですね。
勉強になります。
No.3
- 回答日時:
こちらも実際に試してみました。
VC++6.0で、console applicationを作って、cmd1.exeを作成し、c:\windows\commandに入れました。
c:\上から、cmd1とタイプすると、
C:\WINDOWS\COMMAND\CMD1.EXE
と表示されます。
この違いはなんだろう?
ていうか、argv[0]にフルパスが含まれるのは大分昔からの仕様だと思ってたんだけど・・・。
No.2
- 回答日時:
今unixの環境が手元に無いんだけど、MS-DOSで実行すると
argv[0]はフルパスを返します。
"c:\windows\デスクトップ\cmd1.exe"のように。
unixでは"/usr/bin/cmd1"を返さないのでしょうか?
"cmd1"のみ?
この回答への補足
回答ありがとうございます。
MS-DOSはあまり経験がないのですが今やってみました。
Windows2000です。
cmd1.exeを作成して、PATHの通った場所にコピーしました。
具体的にはC:\WINNT\system32に入れました。
そしてカレントをC:\に移動して実行しました。
C:\>cmd1.exe
cmd1.exe
cmd1.exeとしか表示されませんでした。
私の説明がまだ不足しているような気がします。
C:\WINNT\system32\cmd1.exe
というパスを何らかの方法で簡単に取得できないかと
苦慮しています。
よろしくお願いします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
初めて自分の家と他人の家が違う、と意識した時
子供の頃、友達の家に行くと「なんか自分の家と匂いが違うな?」って思いませんでしたか?
-
フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
あなたが普段思っている「これまだ誰も言ってなかったけど共感されるだろうな」というあるあるを教えてください
-
映画のエンドロール観る派?観ない派?
映画が終わった後、すぐに席を立って帰る方もちらほら見かけます。皆さんはエンドロールの最後まで観ていきますか?
-
海外旅行から帰ってきたら、まず何を食べる?
帰国して1番食べたくなるもの、食べたくなるだろうなと思うもの、皆さんはありますか?
-
天使と悪魔選手権
悪魔がこんなささやきをしていたら、天使のあなたはなんと言って止めますか?
-
絶対パスの取得について
C言語・C++・C#
-
Cの関数で自分自身のパス取得
C言語・C++・C#
-
<unistd.h>をVisualStudioでつかえるようにする
C言語・C++・C#
-
-
4
FORMが開いているかどうかの確認方法
Visual Basic(VBA)
-
5
GetPrivateProfileStringでiniファイル読込む処理を詳しく知りたいのですが・・・
C言語・C++・C#
-
6
cout と cerrの違い
C言語・C++・C#
-
7
C言語のポインターに関する警告
C言語・C++・C#
-
8
C言語 配列の長さの上限
C言語・C++・C#
-
9
C++ vectorに配列をプッシュしたい
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
エクセルvbaでdocuworksprinter...
-
エクセルVBAで一つ上の階層...
-
コマンドプロンプトのコピー関...
-
Excel 相対パス
-
xcopyコマンドの進行状況を表示...
-
VBS パスに変数を入れたい
-
fopenでのパス指定
-
【VBA】ExcelマクロでCSVファイ...
-
エクセルのマクロで特定フォル...
-
SaveAsの保存先について
-
開いているファイルを削除し、...
-
ShellExecuteでエクセルファイ...
-
EXCEL(VBA)で指定フォルダ内の...
-
VBA★PDFをPDFアプリで印刷し...
-
ExcelVBAの使い方 ¥の使い方...
-
A列に記載されているフォルダ...
-
エクセルマクロでファイル名の...
-
【VB.NET】App.configにファイ...
-
Excel2010VBAでエラーが出る相...
-
(GCCコンパイラ)動的リンクを絶...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
エクセルvbaでdocuworksprinter...
-
Excel 相対パス
-
xcopyコマンドの進行状況を表示...
-
エクセルのマクロで特定フォル...
-
エクセルVBAで一つ上の階層...
-
【VBA】ExcelマクロでCSVファイ...
-
コマンドプロンプトのコピー関...
-
A列に記載されているフォルダ...
-
ExcelVBAの使い方 ¥の使い方...
-
EXCEL(VBA)で指定フォルダ内の...
-
【VB.NET】App.configにファイ...
-
SaveAsの保存先について
-
outlook開けない
-
Eclipse
-
VBAでパワーシェルを実行したい...
-
fopenでのパス指定
-
指定したフォルダ内の最新ファ...
-
開いているファイルを削除し、...
-
VBA★PDFをPDFアプリで印刷し...
-
ExcelのVBAで上書き保存を確...
おすすめ情報