こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

コマンドプロンプトにおけるコマンドライン引数の展開

こんにちは。

コマンドプロンプトにおける、コマンドライン引数の展開のされ方について、質問させて下さい。
具体的に言うと、二重引用符で囲まれたコマンドライン引数が、
どのようにして各コマンドに渡されるのかを詳しく知りたいと思っています。
まずコマンドプロンプトが、コマンドラインの特殊文字を展開し、
それらが各コマンドに渡される事は知っています。
特に、2つの二重引用符で囲まれた文字列に含まれる特殊文字は普通の文字として扱われる事、
二重引用符は「\」によってエスケープできる事は知っています。
これらを理解した上で、以下のような事を試しました。
まず、以下のような、1.cというCプログラムを作成し、ビルドしました。
____________________
#include <stdio.h>

int main(int argc,char *argv[])
{
int i;
for(i=1; i<=9; i++)
if(argv[i])
printf("argv[%d]=「%s」\n", i, argv[i]);
return 0;
}

____________________

次に以下のようなバッチスクリプトを作成しました。
____________________
@echo off
echo %%~1:「%~1」
echo %%~2:「%~2」
echo %%~3:「%~3」
____________________

その後、以下のようにして同じコマンドライン引数を、これらのプログラムに渡すと、
以下のような結果になりました。
____________________

C:\Users\kei
>1.exe "\"ab c\"" de
argv[1]=「"ab c"」
argv[2]=「de」

C:\Users\kei
>1.bat "\"ab c\"" de
%~1:「\"ab」
%~2:「c\""」
%~3:「de」
____________________

なぜ両者の出力結果に、違いが出るのかが分からず困っています。
コマンドプロンプロの仕様だと、1.exeの出力は予想通りだったのですが、
1.batの出力では、コマンドライン引数がスペースで区切られていると、
それらを二重引用符で囲んでも、1つの引数としてみなしてくれませんでした。

これだけでは不十分だと思い、以下のように、
Windowsコマンドではない、ダウンロードしてきたlessと
Windowsコマンドであるtypeで、同じ事を試しました。
____________________

C:\Users\kei
>less "\"ab c\"" fa
ab c: No such file or directory
fa: No such file or directory

C:\Users\kei
>type "\"ab c\"" fa
指定されたファイルが見つかりません。
処理中にエラーが発生しました: \ab
パラメータが間違っています。
____________________

この結果をみると、lessでは1.exeと同じようにコマンドラインが解釈され、
moreでは1.batと同じようにコマンドラインが解釈されているようです。

こういった事実は
「まずコマンドプロンプトが、コマンドラインの特殊文字を展開し、
それらが各コマンドに渡される」
というコマンドプロンプトの仕様と矛盾しているので、頭が混乱しています。

こういった問題について、何か御存じの方がいらっしゃれば、情報提供をお願い致します。
長くなりましたが、よろしくお願い致します。

投稿日時 - 2011-08-21 02:37:52

QNo.6956756

困ってます

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

使用環境は Windows ということですよね。
コマンドライン引数を main( int argc, char *arvg ) の argv に分解しているのは、スタートアップルーチン ( Visual C/C++ なら C:\Program Files (x86)\Microsoft Visual Studio XX.X \VC\crt\src\crt0.c あたり ) です。
スタートアップルーチンが "" で囲まれた文字列から "" を取り除いたりしているのだと思います。

#include <windows.h>
#include <stdio.h>

int main(int argc,char *argv[])
{
printf( "%s\n", GetCommandLine() );
return 0;
}

としてみると、コマンドプロンプトから起動したときに渡されたコマンドライン引数がどうなっているか確認できます。

投稿日時 - 2011-08-21 05:15:26

お礼

御回答ありがとうございます。

GetCommandLine() を使えば、コマンドプロンプトで処理された後の
コマンドラインが表示されました。
貴重な情報ありがとうございました。

投稿日時 - 2011-08-21 12:05:55

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.2

一部訂正です。
>コマンドライン引数を main( int argc, char *arvg ) の argv に分解しているのは

>コマンドライン引数を main( int argc, char *arvg[] ) の argv[] に分解しているのは
の間違いです。

投稿日時 - 2011-08-21 05:17:52

あなたにオススメの質問