背景
Windowsでは、パスやファイル名、フォルダ名に長さの制限が設けられており、その制限を超えると「指定されたファイル名は、無効かまたは長すぎます。」といった、様々なエラーが発生します。
また、Pythonによるファイル操作においてもエラーが発生します。私自身、畳み込みニューラルネットワーク(CNN)をはじめ、Pythonを使って、インターネットから取得した画像を操作することがよくありますが、長すぎるファイル名が原因で、画像が存在しているにもかかわらず、FileNotFoundError
が発生したことがありました。
目的
前述したような問題を解決する1つの方法は、単純にファイル名を短くすることです。
しかし、場合によっては何千何万枚のファイル名を変える必要があり、手作業ではほぼ不可能な時があります。私自身、CNNを用いてAIに学習させるときは、何千何百といった画像を使います。
また、Windowsには、選択したファイル名を一括で変更する機能があります。しかし、この機能は「共通名 (連番)拡張子」というように、共通名の最後に(連番)が付くため、任意の箇所に連番を付けることができません。また、何千何万枚もファイルがある場合、全て選択するには手間がかかります。
そこで今回は、次のようなディレクトリ構成にある画像のファイル名を、一括、任意の名前、および一瞬で変更するPythonスクリプトを作成しました。
コーディング
コード全体
下記がコードの全体です。全11行で、ライブラリもos
しか使わない非常にシンプルなものになっています。
import os
dir_folders = input("\n- フォルダ名を入力してください: ")
dir_pictures = os.listdir(dir_folders)
for i in dir_pictures:
number = 1
for j in os.listdir(dir_folders + "/" + i):
ext = os.path.splitext(j)[1]
file_before = dir_folders + "/" + i + "/" + j
file_after = dir_folders + "/" + i + "/" + i + "_" + str(number) + ext
os.rename(file_before, file_after)
number += 1
コードの説明
次からコードの説明をします。先ほどのディレクトリ構成の図と合わせて説明します。
import os
1行目は、今回使うos
というライブラリをインポートしています。
dir_folders = input("\n- フォルダ名を入力してください: ")
2行目は、input
関数を使って、ターミナルで「folderディレクトリ」の名前を入力し、それをdir_folder
に格納しています。
dir_pictures = os.listdir(dir_folders)
3行目は、os.listdir
を使って、「folderディレクトリ」にある各「サブディレクトリ(pictureディレクトリ1, pictureディレクトリ2 etc.)」の名前を取得し、dir_pictures
に格納しています。なお、次のように、各「サブディレクトリ」の名前はリストで格納されます。
for i in dir_pictures:
number = 1
for j in os.listdir(dir_folders + "/" + i):
ext = os.path.splitext(j)[1]
file_before = dir_folders + "/" + i + "/" + j
file_after = dir_folders + "/" + i + "/" + i + "_" + str(number) + ext
os.rename(file_before, file_after)
number += 1
4行目から8行目は、for
文を使って、各「サブディレクトリ」内の画像に対して、順番に名前の変更を行っています。
名前の変更には、os.rename
を使います。os.rename
では、第一引数に変更前のファイルのパス、第二引数に変更後のファイルのパスを指定します。
今回、file_after
を見てもらうとわかるように、変更後のファイル名が「(サブディレクトリ名)_(連番)(拡張子)」となるようにしています。また、拡張子は、os.path.splittext
を使って取得し、変更前と変更後の拡張子が同じになるようにしています。
実行
「folderディレクトリ」があるディレクトリで、ex_rename_file.py
を実行します。実行すると、次のように「folderディレクトリ」の名前の入力を求められるため、入力してEnterを押します。
結果
下図が結果です。今回、rename_test
という「folderディレクトリ」に、cat
, dog
, elephant
, giraffe
, lion
の5つの「サブディレクトリ」があり、その中にそれぞれ画像が複数入っています。変更前と変更後を比較すると、全ての画像ファイルの名前が「(サブディレクトリ名)_(連番)(拡張子)」に変更されていることがわかります。
まとめ
数行の記述で、複数の画像のファイル名を、一括、任意の名前、および一瞬で変更するPythonスクリプトを作成しました。
今回は、サブディレクトリ内に数枚しか画像がありませんでしたが、何千何万枚ある場合でも問題なく動作します。
また、画像ファイルが対象でしたが、実際は、txtやpyなど、他のファイルの名前を変更する場合でも動作します。
最後に、今回がはじめての投稿なので、質問や不備、改善点などがありましたら、是非連絡してください。
GitHubのレポジトリ
参考