こんにちは!今回はバッチで拡張子を除いたファイル名を取得する方法を紹介していこうと思います。
DIRコマンドは、たくさんあるWindowsコマンドの中でも最もポピュラーなコマンドの一つで、ファイルやフォルダの情報をリストアップするのによく使います。
ですが、これを素直に実行してしまうと、余計な情報を多く含んでしまい、目的が達成できないことがあります。
今回はファイルの拡張子を除いたファイル名のみを取得するバッチファイルのサンプルを紹介していきます。
やりたいこと
特定のフォルダから拡張子を取り除いたファイル名の一覧を取得したい。
今回サンプルとしてCドライブ直下に「Temp」というフォルダを作成し、中にはいくつかのテキストファイルを置いてみました。このTempフォルダにDirコマンドでファイル名の一覧を取得し、取得したデータからファイル名のみを取り出すという形で実現していきたいと思います。
スクリプト例
上記の動作を実現する例として、下記の様にスクリプトを作成してみました。
@echo off setlocal enabledelayedexpansion for /f %%A in ('dir /b c:\temp\') do set fileName=%%~nA & echo !FileName! endlocal pause
Dirを実行する対象のフォルダパスを変更することで、他のパスにも対応できると思います。
※Dir /b ディレクトリパス はそのディレクトリ内にあるファイル名を出力するコマンドです。
情報取得はファイルごとに行われるので、その度に実行したいコマンドがあれば青マーカー部分に記述してあげればOKです。その際、使用した変数の両サイドには「%」ではなく「!」を付けてください。
また今回のコツは、「パスの表示方法」を工夫することにあります。
解説
Dirの役割
「Dir」コマンドはフォルダやファイルの一覧を取得するコマンドです。単体で実行した場合は、今現在のカレントフォルダのフォルダとファイルの一覧を出力します。そのため、実際にはファイルパスを指定してそのフォルダ内にあるデータの一覧を取得します。
Dir [ファイルパス]
ですが、そのまま実行すると、冒頭の様な日付や時間、余計なメッセージなどが含まれているため、少し扱いが面倒です。バッチファイル内で実行する際はオプションを使うことで必要なデータのみを抜き出すのが一般的です。
「/b」を付けると、ファイル名のみを出力してくれます。
Dir /b [ファイルパス]
バッチの中ではこの形で実行することが非常に多いです。
ですが、このままでは拡張子が残ったままになってしまいます。
これを処理するためには「1行ずつデータを処理する」必要があります。
For文の役割
for /f %%A in ('[コマンド]') do set [保存用変数名]=%%A
上記のコマンドは、シングルクオーテーション:「'」に囲まれた[コマンド]を実行し、その結果を%Aに取り込むものです。%Aは変数ですが、バッチファイルの中では%%Aと表記しないと正しく動きません。For文はバッチファイルの中でしか使えないので、必然的に%%Aになりますね。
またこの%Aは実行の際に引数として扱われる様で、他の変数とはふるまいが違います。
今回使用した「%~」が使えるのもその特性のおかげです。
[コマンド]は「Dir /b フォルダパス」を使っていますので、ファイルごとに行われます。
この場合ですと、フォルダパス内にあるファイルを1つ読み込む毎にdo以下のコマンドが実行されます。
setlocal enabledelayedexpansionの役割
「setlocal enabledelayedexpansion」は遅延環境変数を有効にするコマンドです。
遅延環境変数はここでは詳しく説明しませんが、「!」を両端に置いた変数を使うためのコマンドです。
For文の中の変数は「set」コマンドで代入してもすぐに中身が変化するわけではありません。
変数の値が変わるのは、For文が終わった後になります。そのため、For文中に代入した値によって処理を変えたい場合、うまくいきません。
そういった場合この遅延環境変数を有効にしておけば、「%変数名%」の代わりに「!変数名!」を使用することで、For文中で変化した変数値を使って処理を進めることができます。
「For」を使う際の一種のおまじないだと思ってもらえると良いと思います。
スクリプト例では一度[保存用変数]に保存していますが、必要が無ければ下記の様にしても良いと思います。
for /f %%A in ('dir /b c:\temp\') do echo %%~nA
ファイルパスから欲しい情報を抜き出す「%~」の役割
%~の後に特定のアルファベットを付加することで、取得したファイルパスを操作することができます。この場合ですと、For文で取得したファイルパスが「%A」に取得されますので、「%~#A」と表記する形です。※#は任意のアルファベット
操作できる内容と対応するアルファベットを簡単に表にまとめてました。
追加するアルファベット | 表示される内容 | 表示例 |
---|---|---|
%~d○ | パスのドライブ名 | C: |
%~p○ | ドライブ以下のディレクトリパス | \Temp\ |
%~n○ | ファイル名 | test |
%~x○ | 拡張子名 | .txt |
%~f○ | すべてのファイルパス | C:\Temp\test.txt |
これらは組み合わせることで、ある程度抜き出すファイルパスを自由に変更することができます。
追加するアルファベット | 表示される内容 | 表示例 |
---|---|---|
%~dp○ | パスのディレクトリ | C:\Temp\ |
%~nx○ | ファイル名と拡張子 | test.txt |
%~dpnx○ | 全てのファイルパス(%~fと同じ) | C:\Temp\test.txt |
%~pxnd○ | 全てのファイルパス(%~fと同じ) ※順番を入れ替えても正しいファイルパスになってしまう | C:\Temp\test.txt |
注意点としては、○に入る変数名は数字かアルファベット1文字でしか指定できません。
しかも、そのほとんどの場合あらかじめ渡されたバッチファイルへの引数か、For文内の変数でしか使用することができません。※無理やりやる方法がないとも言えませんが・・・。→おまけ
自分で用意した%VALUE%などにパスを格納して、%~nVALUE%のような形にしても実行できません。
あとがき
今回はDirコマンドでファイル拡張子を削除してファイル名を取得する方法を通して、「For文」と「%~」の使い方を簡単ですが紹介させていただきました。
実際の現場ではログファイル等を出力する際に、下記の様に出力することがままあります。
echo [ログメッセージ] >> \\[サーバー名]\[ログ保管先]\%COMPUTERNAME%.txt
このコマンドですと、「サーバーのログ保存先にコンピュータ名でログファイルを置く」みたいな感じですね。すると、このログが出力できているコンピュータ名を取得したくなります。
そういったケースで拡張子を残さずにファイル名が取得できれば、そのまま実行したコンピュータ名一覧が完成するわけです。
もちろんこう言ったケース以外にも利用方法はたくさんあります。
「%~」で有名なのはやはり「%~0」でしょうかね。「%0」はバッチを実行した時にバッチ本体があるフルパスが格納されます。そのため、「%~dp0」でバッチファイルの置いてある場所を取得するのは常套手段だと思います。
まぁ、たくさんの用途がありますので、アイディアを駆使して使ってもらえると嬉しいですw
おまけ ー普通の変数を引数にして無理やりやる方法ー
記事内では取り扱いませんでしたが、通常の変数を引数の形に変換してしまう方法です。
簡単に行ってしまえば、サブルーチンへ引数として変数を渡してしまえば、自分で用意したファイルパスでも「%~」を使って文字列を抜き出すことができます。
@echo off
set Test_Path=C:\Temp\test.txt
call :SUB %Test_Path%
pause
exit
:SUB
echo %~n1
exit /b
「:SUB」はサブルーチンです。「%Test_Path%」を第1引数として引き渡しています。
サブルーチンに引き渡された引数は「%1」に格納されますので、それを「%~n1」の形にすることでファイル名である「test」が出力されるという仕組みです。
何かのお役に立てれば幸いです。
コメント
%~pcnd○
じゃなくて
%~pxnd○
の間違いでは?
コメントありがとうございます!
確かにご指摘の通りですね・・・cとxのタイプミスだと思います。よくあるミスとは言えまさか自分のところでやってしまうとは・・・ご指摘ありがとうございました!