【Python】ファイルを新しい順に連番リネーム+曲名変更

自作プログラム

以前の記事で、ファイルの作成順に連番をつけるPythonスクリプトをご紹介しました。

このスクリプトは、例えばフォルダーに

  • ファイル1.m4a
  • ファイル2.mp3
  • ファイル3.m4a

のようなファイルがあるとすると、

  • [01] ファイル1.m4a
  • [02] ファイル2.mp3
  • [03] ファイル3.m4a

のようにファイル名を変更するものです。

今回は、さらに「曲名」属性を変更する操作を追加してみました。

スポンサーリンク

コード

  • mp3
  • mp4
  • m4a

に対応しています。

# -*- coding: utf-8 -*-
#========================================
start_num = 1
#連番を何番から始めるか

insert_front = "["
#連番の前に追加する文字列
insert_back = "] "
#連番の後に追加する文字列

order_sign = "熙/ "
#曲名の先頭に追加する並べ替え用文字列

reset = False
#連番削除モードの設定
#Trueで有効化、Falseで無効化
#有効化すると、曲名の先頭に追加した並べ替え用文字列も削除する
#========================================

import platform
import os
import sys
import glob
import re
from mutagen.easyid3 import EasyID3
from mutagen.mp4 import MP4

ext_list = ["m4a", "mp3"]
#リネーム対象の拡張子のリスト

def get_creation_date(path_to_file):
    """
    OSがWindowsかUnix系の場合はファイルの作成日時を、それ以外の場合は更新日時を返す。
    クロスプラットフォームに対応。
    """
    if platform.system() == 'Windows':
        return os.path.getctime(path_to_file)
        #Windowsの場合
    else:
        stat = os.stat(path_to_file)
        try:
            return stat.st_birthtime
            #Unix系の場合
        except AttributeError:
            return stat.st_mtime
            #その他(Linux系など)の場合は更新日時で代替

def write_title_mp3(path_to_file, title):
    """
    mp3に曲名を書き込む
    :param path_to_file: 楽曲ファイルのパス
    :param title: 書き込む曲名
    """
    meta_data = EasyID3(path_to_file)
    try:
        title = meta_data["title"][0]
        #すでに曲名が設定されている場合
        if re.match(order_sign, title):
            title = title[len(order_sign):]
            #すでに先頭に並べ替え用文字列がある場合、削除
    except KeyError:
        pass

    if not reset:
        title = order_sign + title
    meta_data["title"] = title
    meta_data.save(path_to_file)
    #曲名を書き込む

def write_title_mp4(path_to_file, title):
    """
    mp4またはm4aに曲名を書き込む
    :param path_to_file: 楽曲ファイルのパス
    :param title: 書き込む曲名
    """
    meta_data = MP4(path_to_file)
    try:
        title = meta_data.tags["\xa9nam"][0]
        #すでに曲名が設定されている場合
        if re.match(order_sign, title):
            title = title[len(order_sign):]
            #すでに先頭に並べ替え用文字列がある場合、削除
    except KeyError:
        pass

    if not reset:
        title = order_sign + title
    meta_data.tags["\xa9nam"] = [title]
    meta_data.save(path_to_file)


args = sys.argv
if len(args) < 2:
    print("[ERROR]:処理するフォルダのパスをコマンドライン引数で入力してください")
    exit()
    #入力が1つもなかった場合
folder = args[1]
#処理対象のフォルダを取得

paths = []
for ext in ext_list:
    search_path = os.path.join(folder, "*." + ext)
    paths.extend(glob.glob(search_path))
    #リネーム対象となるファイルのパスを取得

times = [get_creation_date(p) for p in paths]
#ファイルの作成日時のリスト

temporal_list = list(zip(times, paths))
temporal_list.sort(reverse=True)
#作成日時が新しい順にソート
times, paths = zip(*temporal_list)
#配列を分離
del times, temporal_list

keta = len(str(len(paths)))
#追加する連番の桁数

for i, file_path in enumerate(paths):
    file_dir, file_name = os.path.split(file_path)
    #パスをフォルダとファイルに分割
    file_name, file_ext = os.path.splitext(file_name)
    #ファイル名と拡張子に分割

    rm = re.match(
                  re.escape(insert_front) + r"\d+?" + re.escape(insert_back) + r"(.+)",
                  file_name
                  )
    if rm != None:
        file_name = rm.group(1)
        #すでにファイル名の先頭に連番が入っている場合、連番以外を取り出す

    #曲名が設定されている場合、曲名を 並べ替え用文字列 + 曲名 に変更
    #曲名が設定されていない場合、曲名に 並べ替え用文字列 + ファイル名 を書き込む
    if file_ext == r".mp3":
        write_title_mp3(file_path, file_name)
        #拡張子がmp3の場合
    elif file_ext == r".m4a" or r".mp4":
        write_title_mp4(file_path, file_name)
        #拡張子がm4aまたはmp4の場合

    if reset:
        #連番削除モードが有効の場合
        new_name = os.path.join(
                                file_dir,
                                file_name + file_ext
                                )
    else:
        file_num = str(start_num + i).zfill(keta)
        #ゼロ埋めで連番を作成

        new_name = os.path.join(
                                file_dir,
                                insert_front + file_num + insert_back + file_name + file_ext
                                )

    os.replace(file_path, new_name)
    #クロスプラットフォームに対応するため、.renameではなく.replaceを使用

上記スクリプトのうち、

#========================================
start_num = 1
#連番を何番から始めるか

insert_front = "["
#連番の前に追加する文字列
insert_back = "] "
#連番の後に追加する文字列

order_sign = "熙/ "
#曲名の先頭に追加する並べ替え用文字列

reset = False
#連番削除モードの設定
#Trueで有効化、Falseで無効化
#有効化すると、曲名の先頭に追加した並べ替え用文字列も削除する
#========================================

の部分にユーザーが任意の値を指定します。

resetTrueに設定すると

  • ファイル名に付加された連番部分
  • 曲名に付加された並べ替え用文字列

を削除します。
間違えて違うフォルダにスクリプトを適用してしまった場合の取り消し用として作りました。
通常の使用ではFalseに設定しておいてください。

get_creation_date関数は以下のサイトから引用しました。

python — Pythonでファイルの作成と変更の日時を取得する方法
私はファイルの作成と修正の日付に基づいていくつかのことをする必要があるが、LinuxとWindows上で実行しなければならないスクリプトを持っています。Pythonでファイルの作成と修正の日...

そのほかの使い方などについては前回の記事をご覧ください。

作成した経緯

私はSDカードに入れた楽曲をカーオーディオ(ダイハツ純正)で聞いているのですが、私が使っているカーオーディオにはiPodのような「最近追加した項目」を表示する機能はありませんし、ファイルの新しい順に再生することもできません。

これでは新しい曲だけ聞きたい気分のときに不都合が生じます。
そこで、擬似的に「最近追加した項目」を再現するために前回の記事でご紹介したスクリプトを作成しました。

そしてSDカード内のフォルダ構造を以下のようにし、「最近追加した項目」フォルダにスクリプトを適用していました。

└─音楽
 ├─最近追加した項目
 ├─邦楽
 ├─洋楽
 └─アニソン

例えば「アニソン」フォルダに新しい曲を追加したときには、「最近追加した項目」フォルダにも同じ曲を追加し、後者だけに連番をつけるという具合です。

ところが、ここで別の不都合が生じました。
カーオーディオで全フォルダの曲を表示する1と、曲が重複して表示されてしまうのです。

例えば「アニソン」フォルダと「最近追加した項目」フォルダに「ABCD」という曲が入っている場合、全曲を表示すると「ABCD」が連続して表示されるのです。

ところでダイハツ純正カーオーディオの場合、「File」ではファイル名が表示され、「Tag」では曲名が表示されるようです。

そこで「最近追加した項目」フォルダに入っている曲の「曲名」属性の先頭に、文字コードの後ろのほうにある漢字(上のスクリプトでは「熙」)を付け足すことで、全曲を表示したときに「最近追加した項目」フォルダ内のファイルが最後尾に並ぶようにするのが、今回ご紹介したスクリプトの目的です。

スクリプトを適用した結果

「File」から「最近追加した項目」フォルダを開くと、ファイル名の連番順に表示されます。

一方、「Tag」から「曲」を選んで全曲を表示すると…

「最近追加した項目」フォルダに入っている曲は曲名の先頭に「熙/」がついているため、最後尾に固まって表示されます。

ちなみに再生画面では曲名が表示されるため、このようになります。

ちょっと気になりますが、まあよしとしています。

脚注

  1. ダイハツの場合、「Tag」→「曲」で表示される

コメント

タイトルとURLをコピーしました