知ることはたのしい

"車輪の再発明"は時間がもったいないと思うから"車輪の設計図"を置いて学習の効率化に役立ちたい。そしてもっと素晴らしいものを開発してくれないかな。

Windowsのバッチで指定ディレクトリとファイルを取得するのを丁寧に解説する

研究でTektronixのオシロスコープ専用のファイル形式isfをcsvに変換する必要があり、単体のファイルを変換するスクリプトは配布されていたのですが、大量のファイルに対して変換を手で行うのは非常に手間なのでバッチで自動化しました。今回は自動化する際に必要となった機能やコードの解説を行っていきたいと思います。
私自身、バッチは初心者なので備忘録かつ初めての人でも理解できるように努めていきます。


はじめに

プログラムについて見ていく前に、そもそもバッチとは何なのかということについて調べていきましょう。

バッチとは

バッチはWindowsコマンドプロンプト(またはPower shell)上で何らかの処理を行うためのプログラムです。一般的に*.bat*.cmdで表されます。コマンドプロンプトで使えるコマンドはもちろん、if文やfor文なども使えるため繰り返し処理や条件に応じて用いるコマンドを変えたいといった場合に非常に使い勝手がいいものだと思います。
私は大量のファイルをpythonで処理することがあるので、対象ファイルを抽出してプログラムに投げる流れをバッチで作成して汎用性をもたせて利用しています。

シェルスクリプトとは違うのか

バッチがWindowsで動作するものであったのに対して、シェルスクリプトMacやLinaxなどUNIX系の環境を対象としたものになります。拡張子は*.sh*.bashが一般的でしょうか。バッチとシェルスクリプトでは文法に違いがあるので移植する際には注意が必要となります。

今回作成したプログラム

実際に作成したプログラムは下記のようになっています。

isf file to csv

ファイルの説明

話の本筋とは関係がないので詳細は割愛しますがcnvrtwfm.exeというのがTektronixの出しているisfファイルをcsvに変換するスクリプトです*1。ダウンロードはこちらからどうぞ。

jp.tek.com

cnvrtwfm.exeは1回につき1ファイルしか変換してくれないのでバッチで指定ディレクトリ内のisfファイルを探索して逐次変換させました。 このバッチは必要であれば自由に使っていただいて構いませんので、使った際の私のディレクトリ構造を記しておきます。バッチのある階層に変換スクリプトが入っているディレクトリ、isfファイルが複数入ったディレクトリがいくつかある構造になっています。

./
├─cnvrtwfm
│   ├─ReadMe.txt
│   └─cnvrtwfm.exe
├─ABC1
│   ├─foo.isf
│   └─bar.isf
├─ABC2
~~
├─ABCn
└─isf2csv.bat

プログラムの解説

それではプログラムについて順に見ていきましょう。まずは1行目の@echo offです。バッチファイルはデフォルト設定だと行うコマンドすべてをプロンプト上に出力してしまい必要なログが流れてしまうので、不要であればこの文を書いておくことで出力を切ることが出来ます。

続いて、2行目のcd /d %~dp0です。cdコマンド自体はあえて説明は不要だと思いますので引数について説明します。/dcdコマンドのオプションで、CドライブからDドライブやNASなど別のドライブに移動する時に使います。

%~dp0%0~dpオプションが付いたものになっていて、バッチを書くなら頻繁に使うことになると思います。まず、%数字はバッチファイルの引数で、$test.bat aaa bbbだと%1aaaに対応し、%2bbbとなります。%0は良く特殊な扱いを受けて、バッチファイルそのものに対応すると言われますが、これを踏まえると%0test.batに対応しているのは自然に理解できるのではないでしょうか。実際%0に入っている値はフルパス指定のバッチファイルになっています*2

さて、~dpはオプションでそれぞれの文字に意味があります。~は変数からダブルクォーテーションを取り除きます。dはドライブ文字(C:やD:など)だけ抽出します。pはファイル名を除いたパスに展開するので、これらを組み合わせるとバッチファイルが置いてあるディレクトリのパスを示すことになります。

最後に、for文について解説して終わりたいと思います。
for文の構造はfor (オプション) %%[アルファベット1文字(a-zA-Z)] in [対象] do [処理内容]となっています。オプションの種類や文法の詳細は参考文献に譲るとして、ここではプログラムで使っている所に限って説明をしていきます。
/dは対象にディレクトリを取るときのオプションになります。今回は対象を./ABC*としているのでカレントディレクトリ下の頭にABCとつくフォルダ全てを順に変数%%iに渡します。ABC*とした場合では正しく動作しなかったので./をつけることが必要な点に注意する必要があるようです。
単純にカレントディレクトリ内のファイルを取得する際はオプションは不要で[対象]に条件を書けば問題ありません。ここでは(*.isf)として全てのisfファイルを入手しています。

まとめ

今回はバッチファイルについて調べるとともにディレクトリとファイルの取得方法について解説を行いました。
よく使う変数%~dp0、for文について少しでも理解していただけたでしょうか。今後、ファイルのリネームなどについても触れていきたいと思っています。

参考文献

web.plus-idea.net

qiita.com






*1:オシロスコープの型番によってスクリプトが対応していたりしていなかったりというのはちょっと問題だと思いますが。

*2:フルパスなのは実行するプログラムの名前なので当然といえば当然ですかね。