【Python】ファイルを新しい順に連番リネーム

自作プログラム

フォルダーに

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

のようなファイルがあったとき、ファイルの作成順に以下のような連番をつけるPythonスクリプトを作りました。

  • [01] ファイル1.m4a
  • [02] ファイル2.mp3
  • [03] ファイル3.m4a
スポンサーリンク

作成した経緯

私は車の運転中にSDカードに入れた音楽を聞いています。

時々、新しく入れた曲だけを聞きたくなるのですが、カーオーディオにはiPhoneのように「最近追加した項目」みたいなものを表示する機能がありません。

音楽ファイルを作成日時や追加日時順に並べる機能もありません1
常にあいうえお順に並びます。

というわけで、「SDカード内に『最近追加した項目』フォルダを追加し、フォルダ内のファイルに作成した順で連番をつける」ことで、新しく追加した曲を擬似的に作成日順に表示させることにしました。

コード

ファイル名の先頭に連番を追加するコードです。

Python3系があればWindowsでもMacでも動きます。

# -*- coding: utf-8 -*-
#========================================
ext_list = ["m4a", "mp3"]
#リネーム対象の拡張子のリスト

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

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

import platform
import os
import sys
import glob
import re

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系など)の場合は更新日時で代替

args = sys.argv
if len(args) != 2:
    print("[ERROR]:処理するフォルダのパスをコマンドライン引数で1つ入力してください")
    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)

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

    file_num = str(start_num + i).zfill(keta)
    #ゼロ埋めで連番を作成

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

上記スクリプトのうち、

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

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

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

の部分はユーザーが任意の値を指定できます。

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

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

実現したかったこと

  • pythonが入っていればMac・Windows・Linuxで動作する(クロスプラットフォーム)
  • 連番をつけるファイルの拡張子を指定することで、意図しないファイルをいじる危険がない
  • 連番の開始番号を指定することで、新しさに関わらず常にトップに表示したい曲に対応2
  • 連番の前後に好きな文字列を追加できる
  • ファイルの更新日時ではなく作成日時順に連番をつける3
  • フォルダに新しく曲が追加された場合、もう一度スクリプトを動かすだけで全てのファイルに連番をつけ直せる

想定している使い方

私の場合、SDカード内に以下のような階層構造でフォルダを作っています。

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

フォルダ名や階層構造は何でも構いません。

最新の50曲は、それぞれのカテゴリーのフォルダと「最近追加した項目」フォルダの2つのフォルダーに入れています。

そして、新しく曲を追加するたびに「最近追加した項目」に前述のスクリプトを適用しています。

スクリプトの使い方は、

python スクリプトのパス 対象フォルダのパス

をコマンドプロンプトで入力するコマンドライン引数の形式です。

すると「最近追加した項目」フォルダ内の曲は、カーオーディオでは常に作成日時順に表示されることになります。

補足

Windowsでファイルをコピーした場合、コピー先のファイルの作成日時がコピーした日時になってしまうことがあります。

本記事のスクリプトを正しく動作させるにはファイルのタイムスタンプごとコピーする必要があるため、「TeraCopy」というフリーソフトの使用をおすすめします。
ダウンロードページはこちら

Windows版とMac版の両方あります。

追記

改良版を作りました。

脚注

  1. 私の愛車であるダイハツの場合。他のメーカーはどうなのでしょうか。
  2. 例えば、トップに表示したい2曲の先頭に01と02を手動でつけて、連番は3から始めるようにする。
  3. 更新日時順にすると、例えばアーティストの情報を書き換えただけで先頭にきてしまう。

コメント

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