24
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

pythonなら知ってる!人向けバッチファイルの解説

Last updated at Posted at 2023-09-01

初めに

「バッチファイルの知識が必要になったけど何も分からない...けどpythonなら知ってる...」

という方向けに、バッチでできることをpythonに照らし合わせて紹介します。

いい感じでぬるりとバッチの世界に足を突っ込むことを目的としていますので、各セクションに対する網羅的な解説は行っておりません。

Hello, world.

pythonの場合は、pythonをインストールした後に適当なエディタでコードを作成し、pythonコマンドで実行してあげる必要があります。

バッチファイルの場合は、メモ帳さえあれば実行することができます。簡単ですので、まずはバッチファイルの作成 → 実行までを行いたいと思います。

適当なテキストファイルを作成し、下記のような文字を入力してみましょう。

@echo off

echo Hello, world.
pause

※コードの内容が何を表すのかは現時点で分からなくでOKです。

上書き保存したあと、作成したテキストファイルの拡張子を「.txt」→「.bat」に変更します。

WARNINGが表示されますが、構わず「はい」を選択します。

notion.png

すると、テキストファイルが歯車のアイコンに変わります。ダブルクリックしてファイルを実行してみましょう。

@echo offあり.png

おめでとうございます。無事バッチファイルを起動させることができました。

@echo offは書いておくと幸せになれるコマンドです。もし記述してないとこのような出力結果となります。

@echo off なし.png

いちいちコマンドを1行ずつ表示してしまうので、非常にくどい出力結果となってしまいます。

また「続行するには何かキーを押してください。。。」と表示されていますが、これはpauseコマンドのおかげです。

これがないと、一瞬でプロンプト画面が閉じてしまいますので、処理の中身を確認することができません...。

標準出力

pythonの場合

print('こんにちは')

バッチの場合はechoを使用します。

echo こんにちは

変数

pythonの場合

greeting = 'こんにちは'
print(greeting)

>> こんにちは

バッチファイルの場合

set greeting="こんにちは"

REM 変数の中身を出力する場合は % で囲む
echo %greeting%

>> こんにちは

バッチの場合は set が必要です。

さらに、イコールの前後に空白を入れてはいけません。

REM これはOK
set greeting="こんにちは"

REM これはNG
set greeting = "こんにちは"

コメントアウト

pythonの場合

# これはコメントアウトです

上記ですでに登場していますが、バッチの場合は「REM」を使用します。

REM これがコメントアウトです

for文

個人的に、今回紹介するバッチコマンドの中で一番厄介だと感じるのがこのfor文です。

この記事をご覧いただいている方にとっては何を今更感があると思いますが、pythonでのfor文はこんな感じです。

animals = ['dog', 'cat', 'snake']
for animal in animals:
    print(animal)

>> dog
>> cat
>> snake

inの後ろにイテレータを用意してあげることで、中身をループ処理することができます。

すなわち、文にするとこうなります。

for <入れ物> in <イテレータ>:
    いい感じの処理

イテレータの作り方や中身はその時々ですが、このおおまかな構文は変わりません。

バッチコマンドでも同じ要領でしたら私も幸せだったのですが、バッチコマンドではこの構文にオプションという概念が加わってきます。

すなわち、上記のイテレータ部分が同じ内容でも、オプションによって出力結果が異なります。

本記事では「バッチファイルのfor文なんか複雑で面倒」という認識さえ持っていただけたら幸いです。

ここからいくつか例を紹介しますが、詳細は⧉こちらの記事にて解説されておりますので、ぜひご覧ください(丸投げ)。

ファイル名のループ

プログラムと同じディレクトリにあるファイル名をすべて出力します。

このようなディレクトリ構成だと仮定します。

./
├─main.py  ← 実行するpythonファイル
├─main.bat  ← 実行するバッチファイル
├─test01.txt
├─test02.txt
├─test03.txt
└─demo

pythonを使用して、ルートディレクトリにあるテキストファイル名を出力します。

import os

text_filenames = list(filter(lambda x: str(x).endswith('.txt'), os.listdir('./')))
for filename in text_filenames:
    print(filename)

>> test01.txt
>> test02.txt
>> test03.txt

「.txt」で終了するファイル名を抽出しリスト化 → 順に出力しています。

続いてバッチファイルの場合です。

REM オプションなし
for %%i in ("*.txt") do (
	echo %%i
)

>> test01.txt
>> test02.txt
>> test03.txt

大雑把な処理として

  1. 実行したバッチファイルと同じディレクトリにある「~.txt」ファイルを順番に%%iに格納し、
  2. echo %%iで順番に出力しています。

このように、オプションがない場合はファイル名一覧をイテレーションしてくれます。

ちなみに*ワイルドカードのうちの一つで、「任意の文字0文字以上」を表します。pythonの.+みたいな感じですね。

ちなみに「任意の文字1文字」は?で表します。

フォルダ名のループ

pythonを使用して、ルートディレクトリにあるフォルダ名を出力します。
すなわち「demo」のみ出力されればOKです。

import os

dirs = [
    f for f in os.listdir('./') if os.path.isdir(os.path.join('./', f))
]
for folder_name in dirs:
    print(folder_name)

>> demo

os.listdir()メソッドで取得した要素を、os.path.isdir()メソッドでフォルダかどうか判断しています。

バッチですと、このように記述します。

REM /d オプション使用
for /d %%i in ("*") do (
	echo %%i
)

>> demo

/dコマンドがつくことにより、探索対象がディレクトリ名のみになります。
「directory」の「d」なんですかね。

指定回数ループ

ループで一番想像しやすいのはこのパターンではないでしょうか。

for i in range(0, 3, 1):
    print(f'{i} hello')

>> 0 hello
>> 1 hello
>> 2 hello

※バッチコマンドと比較するためにあえて冗長的に記述しています。

バッチファイルでは/lオプションを使用して実現します。

REM /l オプション使用
for /l %%i in (0,1,2) do (
	echo %%i hello
)

>> 0 hello
>> 1 hello
>> 2 hello

バッチにおけるin (0,1,2)の部分は

(開始値、増分、終了値)

を表します。

pythonの**range()**の中身と記述方法が違うので注意です。

この記事がfor文の解説で占領されそうなので、例はこのあたりまでとします。
逆に言うとそれだけ密度のある内容ですので、ぜひ詳細記事をご覧いただく事を推奨いたします。

if文

続いてif文による条件分岐です。

pythonの場合の例です

weather = 'sunny'
if weather == 'sunny':
    print('プールに行こう')
else:
    print('スポッチャ行こう')

>> プールに行こう

同じ内容をバッチファイルで記述してみます。

set weather=sunny
if %weather% == sunny (
	echo プールに行こう
) else (
	echo スポッチャ行こう
)

>> プールに行こう

for文に比べてだいぶしっくりくるのではないでしょうか。
ifコマンドの基本は下記です。

if 条件 (
    条件が真だった場合の処理
else (
    条件が偽だった場合の処理
)

また、条件で使用できる比較演算子は下記のようなものがあります。

equ 等しい
neq 等しくない
gtr より大きい
geq 以上
leq 以下
lss より小さい(=未満)

関数

受け取った引数の合計を返す関数を考えます。

def add(v1, v2):
    return v1 + v2

result = add(2, 7)
print(result)

>> 9

バッチファイルの場合はこのように記述します。

@echo off

call :ADD 2 7 result

echo %result%

pause

exit /b

:ADD
	REM =================================
	REM args
	REM 	IN1, IN2: 足し算を行いたい数値
	REM 	IN3: 足し算結果を格納する変数名
	REM =================================
	set v1=%1
	set v2=%2

    REM 引数の内容確認
	echo %v1%
	echo %v2%

    REM 第3引数の名前で変数を作成し、第1, 2引数を足した結果を格納する
	set /a %3=%v1% + %v2%

	exit /b

>> 9

「:<処理名>」で、複数の処理を1まとめにして名称を付けることができ、サブルーチンと呼ばれます。

callコマンドを使用して呼ぶことができます。

call :<サブルーチン名>

また、サブルーチン名の後ろに半角スペース区切りで引数を渡すこともできます。
サブルーチン側では%1, %2, ...のように引数の順番を指定して受け取ることができます。

call :<サブルーチン名> hoge piyo

:<サブルーチン名>
    echo %1    >> hoge
    echo %2    >> piyo

お気づきかもしれませんが、サブルーチンでは返り値を指定することができません。
なので、:ADDには「足したい値×2」の他に「計算結果を格納したい変数名」を渡し、サブルーチン内で格納しています。

まとめ

基本的なpythonの構文をベースに、バッチコマンドに置き換えた場合の解説をさせていただきました。

少しでも手助けになれば幸いです。

またご指摘等ございましたらぜひご教示ください。


株式会社ジールでは、初期費用が不要で運用・保守の手間もかからず、ノーコード・ローコードですぐに手元データを分析可能なオールインワン型データ活用プラットフォーム「ZEUSCloud」を提供しております。
ご興味がある方は是非下記のリンクをご覧ください:
https://www.zdh.co.jp/products-services/cloud-data/zeuscloud/

24
27
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?