- ベストアンサー
バッチファイルで<&4と4<%1は何をしているの?
- バッチファイルで標準出力とエラー出力をファイルに書き出す方法を理解していますが、数値が3以上で使用されているコードを見かけました。
- 具体的なコード例としては、「SET /P s1= >NUL <&4」という行で、4というハンドルを用いて標準入力から読み取りを行っています。
- このコードでは、%1(file1.txt)ファイルの行を順番に4というハンドルに読み込み、環境変数s1に代入しています。このような使用法についての詳しい解説はありませんが、バッチファイルの応用的な使用例と言えます。
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
そもそもfindstrはファイルディスクリプター(以下fdと略)0からデータを読むように作られているプログラムです。 で、fdの1に処理結果のデータを書きます。 findstrに限らず多くのコマンドもそうです。 例えばechoはfdの1に書きます。 ということがそもそも理解できていなかったということでしょうかね?<&0 が省略されているわけでは無い。 <&0 や >&1 は無意味なのでCMD.EXEではエラーになるようです。
その他の回答 (6)
- notnot
- ベストアンサー率47% (4900/10358)
① 同じ番号だとエラーになるようですね。 ② ちょっと何を言ってるのか分かりません。 やってみれば良いのでは?
お礼
質問の内容が分かりにくくて申し訳ありませんでした。 再度、説明されて頂きたく思いますが、 ②は①の回答結果によりますので、 まず①のみを説明されて頂きます。 最初にこの質問をした背景を述べておきます。 Paste.CMDには3つのFOR文がありますが、 3番目のFOR文は、 (FOR … SET /P s1= >NUL <&4 …) 4<%1 … となっていて、4<%1 と <&4 の部分があり、 4<%1の部分で、%1がファイルディスクリプタ4に取り込まれて、 <&4の部分で、ファイルディスクリプタ4から取り出しているので、 分かりやすいのですが、 1番目と2番目のFOR文は、 (FOR /F %%0 IN ('FIND /C /V ""') DO SET a1=%%0) <%1 となっていて、<%1 のみで <&の部分がなく、 どのようになっているのかがよく分かりませんでしたので、 今回のような質問をしました。 頂いた回答No4で、 <%1 は 0<%1 の 0 が省略されていることを教えて頂きましたので、 同様に、<&0 の部分も省略されているのではないかと考えて、 おそらく、省略しないと、 FIND /C /V "" <&0 のようになるのではないかと思ったのですが、 これではエラーになりましたので、 1番目のFOR文で、<&0 を省略しないで記述するには、 どのように記述をすればよいかのを教えて頂きたくて、 回答No5の所で①のような質問をしました。 期待していた回答としては、 (FOR /F %%0 IN ('FIND /C /V ""' <&0) DO SET a1=%%0) 0<%1 というような回答を頂きたかったのですが・・・ ただし、このコードではエラーになりますので、 エラーにならないコードを教えて頂けないでしょうか。 よろしくお願いします。
- notnot
- ベストアンサー率47% (4900/10358)
> For文でのファイルディスクリプタの使い方を解説しているサイトがありましたら教えて頂けないでしょうか。 リダイレクトやファイルディスクリプタについて、for文だからと言って特別なことは何も無いです。他のコマンドにおけるリダイレクトやファイルディスクリプタと全く同じです。
お礼
回答ありがとうございます。 リダイレクトやファイルディスクリプタについては、 for文でもfor文でなくても全く同じということですが、 (for文とは直接関係ないのかもしれませんが) 以下のことがよく分からないので、 もし、分かりましたら教えて頂けないでしょうか。 ①<&0を明示的に記述することはできるのでしょうか? 例えば、 (FOR /F %%0 IN ('FIND /C /V ""') DO SET a1=%%0) 0<%1 で、%1の値がファイルディスクリプタ0に入力された後、 ファイルディスクリプタ0に入った値を取り出すには、 <&0 と記述すると思われますが、 (FOR /F %%0 IN ('FIND /C /V ""') DO SET a1=%%0) 0<%1 で、<&0を記述するには、 どのように記述をすればよいのでしょうか。 ②ファイルディスクリプタの数字として、 3以上の値を指定しても0や1と同じように 使えうことができるのでしょうか? 例えば、 (FOR /F %%0 IN ('FIND /C /V ""') DO SET a1=%%0) 0<%1 で、ファイルディスクリプタの数字が、0ではなくて、3を使用して、 (①に相当する<&3も併用して)、記述することはできるのでしょうか。 よろしくお願いします。
- notnot
- ベストアンサー率47% (4900/10358)
ファイルディスクリプタは入出力では常に使います。 echo offを書かずに実行されるコマンドを表示させてみたことはないでしょうか? echo aaa >FILE という内容のバッチファイルを作って実行すると、 echo aaa 1>FILE と表示されます。リダイレクト記号にファイルディスクリプタの数字を書かないと出力は1、入力は0が自動的に設定されます。 また、set と set /p は違う命令なので、入れ替えると違う動作をします。それぞれの意味がわからないと言うことなんでしょうか? コマンドプロンプトでset /?と打つと、説明が表示されます。
お礼
set /? で調べてみました。 SET [変数名=[文字列]] 変数名 環境変数名を指定します。 文字列 変数に割り当てる文字列を指定します。 SET /P 変数=[プロンプト文字列] ユーザーによって入力された入力行を変数の値として設定できるようにします。 リダイレクトによって入力された文字列を変数に設定するので、SETではなくSET /Pということですね。 ありがとうございました。
- f272
- ベストアンサー率46% (8467/18126)
> for文でのハンドルの使い方 for文で特有の使い方というのはありません。どこで使っても入出力をリダイレクトするということだけです。 例えば SET /P s1= >NUL <&4 で/pがついているのは「for文でのハンドルの使い方」とは何の関係もありません。/pがなければ「変数=設定する値」と書きますが、/pがあれば「変数=表示される文字列」となって設定する値の入力まちになります。この例ではそれが4番のファイルから与えられるということです。 ちなみに (FOR /F %%0 IN ('FIND /C /V ""') DO SET a1=%%0) <%1 であれば0<%1と書いてあるのと同じことです。0は省略可能だから<%1となっているのです。他の例と何もかわりはありません。
お礼
回答ありがとうございます。 1番目、2番目のfor文と3番目のfor文は、 違うように見えるけれども、 数字や<&が省略されているだけで、 ファイルハンドルとリダイレクトの使い方自体は、 どちらも同じということですね。 それでも、まだよく分からないことがあります。 1番目の (FOR /F %%0 IN ('FIND /C /V ""') DO SET a1=%%0) 0<%1 では、3番目の<&4に相当する部分がありませんが、 省略すると、暗黙的に、 条件式('FIND /C /V ""')の部分が指定されるのでしょうか。 また、明示的に<&0を指定しようとすると、 (FOR /F %%0 IN ('FIND /C /V ""' <&0) DO SET a1=%%0) 0<%1 (FOR /F %%0 IN ('FIND /C /V "" <&0' ) DO SET a1=%%0) 0<%1 では、エラーになってしまいますが、 明示的に<&0を指定するにはどのように記述すればよいのでしょうか。 3番目の4を0や1に変えると正しく動作しなくなります。 0と1は入力用と出力用なので使えないのかなと思って、 (FOR /F %%0 IN ('FIND /C /V ""' <&6) DO SET a1=%%0) 6<%1 (FOR /F %%0 IN ('FIND /C /V "" <&6' ) DO SET a1=%%0) 6<%1 のようにしてみましたが駄目でした。 よろしくお願いします。
- notnot
- ベストアンサー率47% (4900/10358)
そういう数字を「ファイルディスクリプタ」といいます。 3以上のファイルディスクリプタは予約されてないので、自由にファイルに割り当てて使うことが出来ます。 (FOR /L %%k ~~~ SET /P s1= >NUL <&4 SET /P s2= >NUL <&5 ) 4<%1 5<%2 の部分で括弧内全体のリダイレクトとして、 4番ファイルディスクリプタが 引数1ファイル からの入力 5番ファイルディスクリプタが 引数2ファイルからの入力 にリダイレクトされているので、括弧内で4番から読めば引数1のファイルから読むことになります。 ・ファイルディスクリプタとは何か ・リダイレクトとは何か を知っていれば単なる応用です。 Linuxのシェルだともっと柔軟なことも出来ますね。
お礼
ファイルディスクリプタというのですね。 for文でのファイルディスクリプタの使い方について よく分からないのですが、 例えば、 最初の2つのfor文は、 (FOR /F %%0 IN ('FIND /C /V ""') DO SET a1=%%0) <%1 というようにファイルディスクリプタは使っていないのに、 3つ目のfor文では、ファイルディスクリプタは使っていますが、 最初の2つのfor文でも、 ファイルディスクリプタを使ってできるのですか。 逆に、3つ目のfor文で、ファイルディスクリプタを使わずに できるのでしょうか。 また、SET s1= ではなく SET /P s1= を使っていますが、 SET s1= ではできないのでしょうか。 このあたりのことがよく分かっていません。 よろしくお願いします。
補足
回答ありがとうございます。 3以上の時は特殊な使用法があると思っていましたので、 上記のような質問をしましたが、 質問の仕方がよくありませんでした。 For文でのファイルディスクリプタの使い方が よく分からないので、 For文でのファイルディスクリプタの使い方を 解説しているサイトがありましたら 教えて頂けないでしょうか。 なお、お礼の方のコメントは無視してください。 よろしくお願いします。
- f272
- ベストアンサー率46% (8467/18126)
あなたが推測していることの通りです。 4< とあればハンドル4に入力をリダイレクトしますし、 <&4 とあればハンドル4からの入力をリダイレクトします。 このように括弧で囲まれたブロックまたはサブルーチンの外側の未定義のハンドルにリダイレクトし、&表記を使用して既に開いているファイルを参照することができます。 ハンドルとして使える数字は0から9までですが、すでにあなたをもわかっているように0、1、2は標準入力、標準出力、エラー出力に結び付けられています。
お礼
回答ありがとうございます。 3以上の時は特殊な使用法があると思っていましたので、 上記のような質問をしましたが、 質問の仕方がよくありませんでした。 for文でのハンドルの使い方についてよく分からないので、 解説しているサイトを教えて欲しかったのです。 例えば、 SET /P s1= >NUL <&4 の部分ですが、 SET s1=・・・ではできないのでしょうか。 なぜ/Pがついているのかがよく分かりません。 よろしくお願いします。
お礼
なるほど。そういったことでしたか。 これで①は解決しました。 もし、①の回答が、 ディスクリプター0だからできないという回答だった場合、 0以外(例えば3など)ではできるのですかというのが②なので、 今回の回答で②も解決です。 ありがとうございました。