ファイル名を1つ1つ変更する作業ってだるいですよね。
ダウンロードした画像の名前って、よくわかんないアルファベットの羅列とか多いですし、、
今回は、そんな方のために『ファイル名一括変更プログラム』を組んでみたので、実装コードとその解説をしていきます。
解説とは言っても、めちゃくちゃ簡単なので、サクッと終わります。
プログラムの実行例はこちらです。
さっそく本編へ移りましょう!
ファイル名一括変更プログラムの概要
まずは、今回作成するプログラムの概要を説明します。
今回のプログラムでは、3つ値を指定することで、ファイル名を連番で統一します。
指定する項目
- 変更したいファイルがあるディレクトリ
- 変更したいファイルの拡張子(複数可)
- 変更後にベースとなる名前
以下のように、ベースとなる名前の後ろに番号が追加されます。
この場合、ベースとなる名前は img ですね。
さらに、念のためファイル名変更ログも残すことにします。
これによって、何が何に変更されたのかが後から確認できますね。
ということで、こんな感じのプログラムを組んでいきます。
補足
上の画像は、アルファベットの語順等の関係で、ファイル名の対応が異なって表示されているように見えます。
実際は問題ないので、お気になさらずに。
実装コード
実装コード全体はこちらになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# 必要なライブラリのインポート import os import re from glob import glob import pandas as pd # 一括変更するファイルのディレクトリパスを指定 file_dir = input("directory path >> ") file_dir = re.sub(r"[\"\' ]", "", file_dir) # 一括変更するファイルの拡張子を指定(複数可) exts = input("extensions >> ") exts = [ext.replace(" ", "") for ext in exts.split(" ")] # 新しく統一するファイル名を指定 new_name_temp = input("new name >> ") # 指定した拡張子のファイルパスをすべて取得する file_paths = [] for ext in exts: for path in glob(os.path.join(file_dir, f"*.{ext}")): file_paths.append(path) old_names = [] # 変更前のファイル名のリスト new_names = [] # 変更後のファイル名のリスト for i, file_path in enumerate(file_paths): old_name = os.path.basename(file_path) # 変更前のファイル名 ext = old_name.split(".")[-1] # 拡張子を取得 new_name = f"{new_name_temp}_{i+1:02d}." + ext # 変更後のファイル名 os.rename(file_path, os.path.join(file_dir, new_name)) # ファイル名変更 old_names.append(old_name) # リストに追加 new_names.append(new_name) # リストに追加 # ログをCSVファイルとして保存 logs = pd.DataFrame({"old name": old_names, "new name": new_names}) logs.to_csv(os.path.join(file_dir, "logs.csv"), index=False) |
次の章では、部分的にコードの解説をします。
コード解説
非常にシンプルなプログラムなので、簡単に解説していきます。
1~5行目
必要なライブラリをインポートします。
glob は、ファイルパスを取得する際に使用するモジュールです。
1 2 3 4 5 |
# 必要なライブラリのインポート import os import re from glob import glob import pandas as pd |
8~17行目
ディレクトリのパスと、変更するファイルの拡張子、新しいファイル名の3つを指定します。
こちらのコードでは、 input を使って、実行するたびにユーザーからの入力を促していますが、直接記述してしまっても構いません。
8 9 10 11 12 13 14 15 16 17 |
# 一括変更するファイルのディレクトリパスを指定 file_dir = input("directory path >> ") file_dir = re.sub(r"[\"\' ]", "", file_dir) # 一括変更するファイルの拡張子を指定(複数可) exts = input("extensions >> ") exts = [ext.replace(" ", "") for ext in exts.split(" ")] # 新しく統一するファイル名を指定 new_name_temp = input("new name >> ") |
19~22行目
glob を使って、上で指定したディレクトリ内にあり、指定した拡張子のファイルのパスをすべて取得します。
19 20 21 22 |
# 指定した拡張子のファイルパスをすべて取得する file_paths = [] for ext in exts: for path in glob(os.path.join(file_dir, f"*.{ext}")): |
25~35行目
for文の中で、さきほど glob で取得したファイルのファイル名を変更します。
ログを残すために、変更前のファイル名と変更後のファイル名をリストに格納しておきます。
31行目で、 {i+1:02d} とすることで、連番が1桁のところでも、 01 、 02 、 03 のように2桁で統一できます。
25 26 27 28 29 30 31 32 33 34 35 |
old_names = [] # 変更前のファイル名のリスト new_names = [] # 変更後のファイル名のリスト for i, file_path in enumerate(file_paths): old_name = os.path.basename(file_path) # 変更前のファイル名 ext = old_name.split(".")[-1] # 拡張子を取得 new_name = f"{new_name_temp}_{i+1:02d}." + ext # 変更後のファイル名 os.rename(file_path, os.path.join(file_dir, new_name)) # ファイル名変更 old_names.append(old_name) # リストに追加 new_names.append(new_name) # リストに追加 |
37~39行目
リストに格納しておいたファイル名を、データフレームに変換後、CSVファイルとして保存します。
37 38 39 |
# ログをCSVファイルとして保存 logs = pd.DataFrame({"old name": old_names, "new name": new_names}) logs.to_csv(os.path.join(file_dir, "logs.csv"), index=False) |
これでコードの解説はおしまいです!
おわりに
標準ライブラリのみを使用しているので、そこまで難しくはなかったと思います。
使い道はそう多くないかもしれませんが、『1つの作業を自動化することができた』と言えるので、まあまあ良いことでしょう。
では、今回はここまでとします。
お疲れさまでした。