コマンドプロンプトの出力結果を引数として、別のコマンドを実行させる。
なんてことが出来ることは知ってるんだけど、どうやってやるのかは良く分からない。
おもむろにコマンドプロンプトを立ち上げて、以下のコマンドを打ち込んで見ましょう。
for /?
は?
長くて例文もないし分からないって(怒
って思う自分がいますw
h2>とりあえず、使える例文が知りたいんだよ
自分もネットで先人の知恵を検索しますが、急いでる時なんかは、「詳細説明はいいから、使えるコマンド載せてくれや」などと失礼なことを思ったりもします。
なので、早速使えるFor文を載せましょう。
for /f "delims= usebackq" %i in (`dir /b`) do @echo %i
バッチファイルにする時は、変数に「%」を余分に追加する必要があります。
for /f "delims= usebackq" %%i in (`dir /b`) do @echo %%i
実行するとこうなります。
ちゃんとファイル名が取れてますね。
後は、前後に必要なコマンドとかを付与してあげれば
for /f "delims= usebackq" %i in (`dir /b`) do @echo del ..\sample2\"%i"
実行するとこうなります。
for /f "delims= usebackq" %i in (`dir /b`) do del ..\sample2\"%i"
「@echo」を外してやれば、sample2フォルダにあるsampleフォルダと同一のファイルを削除できますよっと。
コマンドプロンプトって、分からないやつはトコトン分からない
まぁ、半分以上の人が使う時に挫折する(感覚値)やつです。
For文が使えるだけで、バッチ処理できる幅はグッと広がるはずなのに、使い方がイマイチ分からないし、例文も不親切。
っていうか、ピンポイントで使える例文が欲しいんだ!!
と思うこともしばしばです。
自分も、コマンドプロンプトでのループ処理で出来ることは、Excelを使って行コピーで関数を作成してました。
例えば、こんな感じのファイルを用意します。
dir コマンドで出力するとこうなります。
オプションをつけて、dir /b コマンドで出力するとファイル名だけが出力できます。
dir /b >2017_list.txt
などとして、ファイルにファイル名の一覧を出力して、Excelに貼り付けて、copyコマンドやら、なにやらを関数でくっつけて、再度コマンドプロンプトで実行する。
というような方法で複数ファイルへの処理をしていました。
まぁ、コピーや削除、移動ぐらいなら普通にエクスプローラ上の処理でも問題ありません。
ただ、別のフォルダから同一のファイルだけ削除しましょうとか言われると、「・・・」と言葉を失います。
なので、Excelでのコマンド作成って言うのは必須事項でした。
っていうか、ファイルの一覧さえ用意できれば、ウダウダ考えるより早いw
でも、コマンド作成時に間違える可能性がある
Excelでファイル名を筆頭に、コマンドやら対象フォルダやらを並べて、結合して1ファイルずつのコマンドを作成します。
これが普段のやり方。
ただ、毎回手打ちで作るので、コマンドを間違える時が少なからずあるんですよ。
後は、「\」の付け忘れで、対象フォルダが間違ってしまっていたりとかね。
毎回、Excelでコマンド作ったりしていると、フォルダ名を間違えていたりして、実行後に、青ざめたこともあります。
「なんか、上書き確認ばかり発生するなぁ・・・」と思ってたら、moveコマンドの記載ミスで、全て同一ファイル名に変更しようとして上書き確認されていたこともありました。
これが、強制上書きのオプションを付けていらと思うと、ゾッとしますね。
まぁ、Excelもテンプレート的に作っておけばいいんですが、そうすると、管理が面倒になったりするので、バッチファイル一個で済ませたいなと・・・
実は、割と試行錯誤してました。
この実行結果をご覧ください。
for /f "usebackq" %i in (`dir /b`) do @echo %i
そうです。
変数って分かりづらいなとか、引数だのパイプだの悩んで組み上げたfor文では、何故か「2017」っていうファイル名しか取れなかったんですね。
まぁ、「2017 – コピー (2).txt」こんな感じで、半角スペースが入っているので、最初のスペースまでの「2017」が第一引数として「%i」に渡されているからなんです。
> usebackq – 次の新しい表示形式を指定します。
逆引用符で囲まれた文字列がコマンドとして実行され、
一重引用符で囲まれた文字列がリテラル文字列コマンドに
なり、ファイル セットのファイル名を二重引用符で
囲めるようになります。
正直、説明を見ても良く分かりませんが、コレが無いと「(`dir /b`)」の部分でのコマンドが実行できないんですよ。
なので、おまじないってやつですw
なんにしても、ファイル名を正しく取得できないと意味がありません。
新しいオプションdelims
これが正解かは分かりませんが、現時点で望む動作になっているので、とりあえず正解とします。
for /f "delims= usebackq" %i in (`dir /b`) do @echo %i
オプションは「”」の間に全て記述する必要があるようで、分けて記述したら、怒られましたw
delimsってなんだよって人は、コマンドプロンプトのヘルプを参照してください。
> delims=xxx – 区切り文字のセットを指定します。
これは、既定の区切り文字であるスペースとタブを
置き換えます。
今回の問題はファイル名に含まれる半角スペースによって、引数として認識されるファイル名が最初のスペースまでの数文字になってしまったのが問題でした。
なので、引数の区切り文字をデフォルトのスペースから変えてやることで、ファイル名を全て引数にぶち込むことが可能になるわけです。
まとめ
今回は、Delコマンドでやったけど、コマンドを変えてもいいし、@echoのままファイルにリダイレクトしてやれば、コマンドがそのまま出力されるので、それでもいい。
要は、バッチファイルを叩くだけで、必要なファイルに対してバッチ処理をしたかった。
あ、そのまま使って、大切なファイルが消えても責任は取れないので、必ず、サンプルフォルダとかファイルを用意してテストしてください。