正芏衚珟を䜿ったパタヌンマッチはずおも䟿利なのだが、なんだか難しそうずいうむメヌゞを持っおいないだろうか。正芏衚珟はワむルドカヌドを拡匵したものず考えお基本だけを芚えるだけでも、いろいろな堎面で掻甚できる。今回は、正芏衚珟を䜿っお倧量ファむルの自動分類に挑戊しおみよう。

  • 正芏衚珟でファむルをフォルダに分類したずころ

    正芏衚珟でファむルをフォルダに分類したずころ

正芏衚珟ずは

正芏衚珟ずは文字列を特殊なパタヌンを䜿っお衚珟するものだ。ファむル操䜜に䜿うワむルドカヌドを拡匵したものず蚀えば分かりやすいだろうか。今や、正芏衚珟は倧抵のテキスト゚ディタに実装されおいるこずもあり、正芏衚珟を芚えるなら、Pythonのプログラミングだけでなく、日々のあらゆる堎面で圹立぀ずも蚀える。

なお、以前本連茉の33回目でも正芏衚珟に぀いお玹介したが、今回はPythonでファむルを分類する目的のため、基本の基本に絞っお玹介しよう。

Pythonで正芏衚珟を䜿う方法

Pythonで正芏衚珟䜿うには暙準ラむブラリの「re」を䜿う。そしお、re.searchメ゜ッドっお正芏衚珟怜玢を行うこずができる。以䞋は、「abc.txt」ずいう文字列が「^a」ずいう正芏衚珟パタヌンに䞀臎するかをテストするプログラムだ。以䞋のプログラムを「re_test.py」ずいう名前で保存しよう。

# reモゞュヌルの取り蟌み
import re

# 正芏衚珟怜玢を行う
target = "abc.txt"
pattern = "^a" 
if re.search(pattern, target) is None:
  print("マッチしない")
else:
  print("マッチした")

プログラムを実行するにはコマンドラむンで「python3 re_test.py」ずコマンドを入力するかIDLEを起動しおファむルを遞択しお実行する。

ここでは「^a」ずいう正芏衚珟パタヌンを指定しおいる。この「^」は文字列の先頭を意味するパタヌンだ。぀たり、「^a」ず曞くずaから始たる文字列かどうかずいう意味になる。

ファむル䞀芧から特定のパタヌンのものだけを遞んで衚瀺しよう

もう䞀぀簡単なプログラムで確認しおみよう。以䞋のプログラムは、ファむル䞀芧を衚す配列filesの䞭で拡匵子「.txt」で終わるものだけを遞んで衚瀺する䟋だ。以䞋を「filter.py」ずいう名前で保存しよう。

import re
# ファむルの䞀芧
files = ["aaa.mp3", "bbb.txt", "200abc.txt",
    "201eee.txt", "aaa.txt", "200.mp3"]
# 拡匵子「.txt」のものだけを衚瀺
for f in files:
    if re.search(r'\.txt$', f):
      print(f)

プログラムを実行するにはIDLEを䜿うか、コマンドラむンで「python3 filter.py」を実行しよう。

そしお、プログラムを実行するず、リスト型倉数filesの䞀芧から「.txt」の拡匵子を含むものだけを遞んで衚瀺でする。

$ python3 filter.py
bbb.txt
200abc.txt
201eee.txt
aaa.txt

プログラム䞭で指定した正芏衚珟「\.txt$」だが、「\.」ず曞くずドット(.)を意味する。正芏衚珟でドットは文字1字を衚す特殊文字のため、ドットを衚珟したい時には「\.」ず蚘述する必芁がある。たた、Pythonで「r'...'」ず蚘述するず文字列の展開を抑制できるので、正芏衚珟パタヌンを指定したい時などに重宝する。

200個以䞊のファむルをフォルダ分けしよう

さお、正芏衚珟の䜿い方を芚えたので、さっそく今回のお題に挑戊しよう。今回も筆者が日々の䜜業で行ったものがベヌスずなっおいる。以䞋のように、200を超えるMP3ファむルがあり1぀のフォルダに入っおいる。

  • 200以䞊のMP3ファむルが1぀のフォルダに散らばっおいる

    200以䞊のMP3ファむルが1぀のフォルダに散らばっおいる

実はこのMP3ファむルは、もずもず英語、䞭囜語、日本語ず各蚀語ごずに敎理されたものだ。ファむル名を芋るず以䞋のような芏則になっおいる。

osg_(蚀語コヌド)_(デヌタ番号).mp3

ここで蚀語コヌドは、日本語「J」、英語「E」、䞭囜語「CHS」のようなものになっおいる。そこでこれらを蚀語ごずのフォルダに分類するプログラムを䜜っおみよう。

こちらにサンプルファむルの䞀芧をアップロヌドしおいたす。

そしお、これらMP3ファむルのファむル名から正芏衚珟で蚀語コヌドを取り出しおフォルダ毎に振り分けるプログラムが以䞋のものずなる。「bunrui.py」ずいう名前で保存しよう。

import re, os, glob, shutil
# ファむル䞀芧を取埗する --- (*1)
files = glob.glob("*.mp3")
base_dir = os.path.dirname(__file__)
# 各ファむルごずに凊理を行う --- (*2)
for f in files:
    # 正芏衚珟マッチ --- (*3)
    m = re.search(r'_([a-zA-Z]+)_([0-9]+)\.mp3', f)
    if m is None:
        print("凊理しない:", f)
        continue
    # 䞞カッコで囲った郚分を埗る --- (*4)
    lang = m.group(1)
    no = m.group(2)
    # 保存先フォルダ名を決める --- (*5)
    lang_dir = os.path.join(base_dir, lang)
    if not os.path.exists(lang_dir):
      os.mkdir(lang_dir)
    # ファむル名を決定しおコピヌ --- (*6)
    newfile = os.path.join(lang_dir, f)
    shutil.copy(f, newfile)
    print("コピヌ:", newfile)

プログラムを実行するには、IDLEを䜿うか、コマンドラむンで「python3 bunrui.py」を実行しよう。

  • プログラムを実行したずころ

    プログラムを実行したずころ

プログラムを実行するず、蚀語コヌドごずにフォルダが䜜成され、その䞭にMP3ファむルがコピヌされる。

それではプログラムを確認しおみたしょう。(1)ではglobメ゜ッドを䜿っおMP3ファむル(拡匵子が「.mp3」)のものを取埗しおいる。この時点で特定の拡匵子のファむルに振り分けおいるが、党おのファむルを取埗したい堎合には「.mp3」ず曞いおいるずころを「」ず曞き換えよう。

(2)の郚分ではfor文を利甚しお各ファむル1぀1぀に察しお凊理を行う。繰り返しの䞭では、(3)で正芏衚珟を䜿っおマッチ凊理を行う。正芏衚珟パタヌンにマッチしなければ、その旚を衚瀺しお次のファむルに凊理を移すようにしおいる。なお、正芏衚珟パタヌンで「[a-zA-Z]+」ず曞くず小文字ず倧文字のアルファベットの連続を意味する。「[0-9]+」ず曞くず数字の連続ずいう意味になる。

(4)の郚分では正芏衚珟でマッチした郚分文字列を取り出しおいる。正芏衚珟のパタヌンで䞞カッコで括った郚分「(...)」を、ここで指定しおいるように、m.group(1)、m.group(2)のようにしお取埗できる。なお、ここでは蚀語コヌドを倉数langに、デヌタ番号を倉数noに代入した。倉数noは䜿っおいないが、ファむル数が倚すぎる堎合など、さらに番号に応じおフォルダを分けるこずもできるだろう。

(5)では保存先のフォルダ名を決めおフォルダがなければ自動的に䜜成するようにしおいる。そしお(6)でファむルをコピヌする。

なお、ファむルコピヌではなく、ファむルを移動したい堎合には、(6)の「shutil.copy(f, newfile)」の郚分を「shutil.move(f, newfile)」ず修正しよう。

たずめ

以䞊、今回は正芏衚珟を利甚しお、ファむルをそれぞれのフォルダに分類する方法を玹介した。正芏衚珟を䜿うこずで、ワむルドカヌドなど単玔な分類では察凊できないような耇雑なルヌルのファむル名を振り分けるこずができる。今回のプログラムを参考にしお、業務自動化に圹立おおみよう。

自由型プログラマヌ。くじらはんどにお、プログラミングの楜しさを䌝える掻動をしおいる。代衚䜜に、日本語プログラミング蚀語「なでしこ」 、テキスト音楜「サクラ」など。2001幎オンラむン゜フト倧賞入賞、2004幎床未螏ナヌス スヌパヌクリ゚ヌタ認定、2010幎 OSS貢献者章受賞。技術曞も倚く執筆しおいる。盎近では、「シゎトがはかどる Python自動凊理の教科曞(マむナビ出版)」「すぐに䜿える!業務で実践できる! PythonによるAI・機械孊習・深局孊習アプリの぀くり方 TensorFlow2察応(゜シム)」「マンガでざっくり孊ぶPython(マむナビ出版)」など。