Pythonでファイル名の前後に文字列や連番を加えて一括変更
osモジュールとglobモジュールを使って一括でリネーム
osモジュールとglobモジュールを使って、フォルダ内のファイル名の前後に文字列や連番を加えて一括で変更、リネームする。
ファイル構造の例
以下のようなファイル構造を例とする。今回はフォルダ内にはファイルしかない(フォルダがない)ことが前提。
.
└── testdir
├── a.jpg
├── b.jpg
├── c.jpg
├── d.jpg
└── e.jpg
注意
ファイル名の変更を伴う処理なので、失敗しても大丈夫なように、オリジナルのファイルは別に保存しておきましょう。
globモジュールでファイルリストを取得
glob モジュールは Unix シェルで使われているルールに従い指定されたパターンに一致するすべてのパス名を見つけ出します。
11.7. glob — Unix 形式のパス名のパターン展開 — Python 3.5.2 ドキュメント
例えば、glob.glob('./*')
で、カレントディレクトリ内のファイル名とディレクトリ名のリストが取得できる。引数は絶対パスでも相対パスでもOK。
今回の例だと、
import glob
print(glob.glob('./testdir/*'))
# => ['./testdir/a.jpg', './testdir/b.jpg', './testdir/c.jpg', './testdir/d.jpg', './testdir/e.jpg']
というようになる。
a.jpg
ではなく./testdir/a.jpg
のように、引数のパスが加えられた形で取得できる。
glob.glob('./testdir/*.jpg')
というようにワイルドカード*
を使って、特定の拡張子のみを取得することもできる。
以下のパターンマッチが使える。
*
: すべてのものにマッチする?
: 任意の一文字にマッチする[abc]
: a, b, cのいずれかの一文字にマッチする[!abc]
: a, b, c以外の一文字にマッチする
glob
モジュールについてのより詳しい説明は以下の記事を参照。
os.rename()でリネーム
os.rename(src, dst, *, src_dir_fd=None, dst_dir_fd=None)
ファイルまたはディレクトリ src の名前を dst へ変更します。
16.1. os — 雑多なオペレーティングシステムインタフェース — Python 3.5.2 ドキュメント
名前のとおりリネームしてくれるosモジュールの関数rename()
を使う。
import os
os.rename('./testdir/a.jpg', './testdir/a_000.jpg')
とすると、a.jpg
がa_000.jpg
にリネームされる。
str.format()でゼロ埋めの連番を生成する
例えば、数十個のファイルに連番を加える場合、0
や1
ではなく、00
や01
にしたい。このように0埋めしたい場合は、str.format()
メソッドを使う。
str.format(args, *kwargs)
文字列の書式化操作を行います。このメソッドを呼び出す文字列は通常の文字、または、 {} で区切られた置換フィールドを含みます。 4. 組み込み型 — Python 3.5.2 ドキュメント
書式指定文字列の文法
書式指定文字列は波括弧 {} に囲まれた “置換フィールド” を含みます。置換フィールドの文法は以下です:
replacement_field ::= "{" [field_name] ["!" conversion] [":" format_spec] "}"もっと簡単にいうと、置換フィールドは field_name で始められます。これによって指定したオブジェクトの値が、置換フィールドの代わりに書式化され出力に挿入されます。field_name の後に、感嘆符 '!' を挟んで conversion フィールドを続けることができます。最後にコロン ':' を挟んで、format_spec を書くことができます。これは、置換される値の非デフォルトの書式を指定します。
6.1. string — 一般的な文字列操作 — Python 3.5.2 ドキュメント
とりあえず0埋めしたい場合は以下のようにする。
# 3を2桁でゼロ埋め
print('{0:02d}'.format(3))
# => 03
# 4と6をそれぞれ3桁と4桁でゼロ埋め
print('{0:03d}, {1:04d}'.format(4, 6))
# => 004, 0006
format()
についてのより詳しい説明は以下の記事を参照。
ファイルの前に文字列・連番を追加するコードの例
os.path.basename()
でファイル名を取得し、その前に文字列や連番を追加してから、os.path.join()
で元のパスと連結する。
以下の例では、すべてのファイル名の前にimg_
を追加する。
import os
import glob
path = "./testdir"
files = glob.glob(path + '/*')
for f in files:
os.rename(f, os.path.join(path, 'img_' + os.path.basename(f)))
結果は以下のようになる。
.
└── testdir
├── img_a.jpg
├── img_b.jpg
├── img_c.jpg
├── img_d.jpg
└── img_e.jpg
連番を追加する場合はfor文
のところをこんな感じに変える。enumerate()
でfor文
を回すことで、0から順番にカウントされる数値を取得できる。ここでは三桁で0埋めしている。
for i, f in enumerate(files):
os.rename(f, os.path.join(path, '{0:03d}'.format(i) +
'_' + os.path.basename(f)))
結果はこう。
.
└── testdir
├── 000_a.jpg
├── 001_b.jpg
├── 002_c.jpg
├── 003_d.jpg
└── 004_e.jpg
000
からじゃなくて001
から始めたい場合は、enumerate
の第二引数を1
とする。
for i, f in enumerate(files, 1):
os.rename(f, os.path.join(path, '{0:03d}'.format(i) +
'_' + os.path.basename(f)))
こうなる。
.
└── testdir
├── 001_a.jpg
├── 002_b.jpg
├── 003_c.jpg
├── 004_d.jpg
└── 005_e.jpg
ファイルの後ろに文字列・連番を追加するコードの例
os.path.splitext()
で拡張子とルートパスに分割してから、ルートパスの方に文字列や連番を追加する。以下の例では、すべてのファイル名の後に_img
を追加する。
import os
import glob
files = glob.glob('./testdir/*')
for f in files:
ftitle, fext = os.path.splitext(f)
os.rename(f, ftitle + '_img' + fext)
結果はこうなる。
.
└── testdir
├── a_img.jpg
├── b_img.jpg
├── c_img.jpg
├── d_img.jpg
└── e_img.jpg
ファイルの前に文字列・連番を追加するときと同様に、連番を追加する場合はfor文
のところを変える。
for i, f in enumerate(files):
ftitle, fext = os.path.splitext(f)
os.rename(f, ftitle + '_' + '{0:03d}'.format(i) + fext)
.
└── testdir
├── a_000.jpg
├── b_001.jpg
├── c_002.jpg
├── d_003.jpg
└── e_004.jpg