Pythonでファイル名が1・10・2の順になる|数字順に並べる

Pythonでファイル名が1・10・2の順になる|数字順に並べる

記事
IT・テクノロジー
カテゴリ:Python・ファイル整理

「写真_1.jpg、写真_2.jpg、写真_10.jpgの順で処理したいのに、10が2より先に来る」。
Pythonでファイル名のリストを並べるときは、名前全体ではなく、番号を数値にして比べると直せます。

1 文字の順番と、番号の順番は違う

sorted(names)で名前の文字列をそのまま並べると、写真_1.jpg、写真_10.jpg、写真_2.jpgの順になります。数字が入っていても、ファイル名は文字列だからです。

順番だけが問題なら、元のファイル名を変更する必要はありません。並べ替えに使う番号だけを取り出します。

2 3つの名前で試す

下の例は、名前が「写真_半角の番号.jpg」の形でそろっている場合に使います。フォルダーの場所を含まない、ファイル名だけのリストが対象です。

Python 3が使える環境で、コード部分だけをUTF-8の「sort_filenames.py」として保存し、普段使っている方法で実行してください。追加ライブラリは不要です。ここではLinux/Python 3.12.14で確認しています。

実物の画像は用意しなくてかまいません。この例は3つの文字列を並べて表示するだけで、ファイルの読み込み・保存・移動・名前変更はしません。

【プログラムここから】
import re

names = ["写真_1.jpg", "写真_10.jpg", "写真_2.jpg"]
pattern = re.compile(r"写真_([0-9]+)\.jpg")
bad_names = [name for name in names if pattern.fullmatch(name) is None]
if bad_names: raise ValueError(f"対象外の名前です: {bad_names[0]!r}")

ordered_names = sorted(names, key=lambda name: int(pattern.fullmatch(name).group(1)))
for name in ordered_names: print(name)
【プログラムここまで】

表示される結果
写真_1.jpg
写真_2.jpg
写真_10.jpg

「プログラムここから/ここまで」の行はコードに含めません。この例では各行の先頭に空白は不要です。

pattern.fullmatchで名前全体の形を先に確認し、対象外がなければ番号の部分をintで整数にして並べます。sortedのkeyは「何を比べて並べるか」の指定です。

並べ替えた結果はordered_namesに入ります。元のnamesの並び順と、名前の文字列はそのままです。

3 自分の一覧に使う前に、名前の形を確認する

まずnamesの3件を、自分のファイル名の例に置き換えて、表示だけで確認します。このコードのまま使えるのは「写真_1.jpg」のような形です。.JPGや.png、別の接頭辞には、そのままでは対応しません。

たとえばREADME.txtや写真_2026_2.jpgが混ざると、「対象外の名前です」というValueErrorで止まります。対象外の名前を勝手に飛ばしたり、どの数字で並べるか推測したりしないためです。

・写真_2.jpgと写真_02.jpgは、どちらも番号2として比べます。名前の0は消えず、この2件の前後は元のリスト順のままです。
・年と連番など、数字が2か所ある場合は、どちらを優先するか先に決めます。この例では扱いません。
・数字のない名前や別形式の名前を、最後に回すか除外するかも別のルールです。必要なファイルを落とさないよう、混ぜたまま流用しないでください。

実際の処理につなぐときは、意図した順になったordered_namesを使います。元のnamesを使い続けると、処理の順番は変わりません。フォルダーの画面表示順を変更するコードでもありません。

まずは、どの番号を基準にしたいかと、表示された順番が合っているかを確かめましょう。

参考:Python公式ドキュメント
ソートのテクニック(sorted、key、同じキーの順序)
re.fullmatch(名前全体の形式確認)

サービス数40万件のスキルマーケット、あなたにぴったりのサービスを探す