【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)
    #複数のOSに対応するため、.renameではなく.replaceを使用

上記スクリプトのうち、

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

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

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

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

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

https://www.it-swarm.dev/ja/python/python%E3%81%A7%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E4%BD%9C%E6%88%90%E3%81%A8%E5%A4%89%E6%9B%B4%E3%81%AE%E6%97%A5%E6%99%82%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/958448471/

実現したかったこと

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

想定している使い方

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

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

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

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

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

スクリプトの使い方は、

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

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

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

補足

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

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

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

追記

改良版を作りました。

脚注

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

Amazonプライム(月額税込み500円)に登録すると……
  • 対象商品のお急ぎ便お届け日時指定便が無料
  • 10,000本以上の映画やテレビ番組が見放題
  • 1,000冊以上の電子書籍が読み放題
  • 30日間の無料体験あり(無料体験期間中のキャンセルも可能)
\ そのほかの特典もチェック /

自作プログラム
スポンサーリンク
\気に入ったらシェアしてください/
ジョー・ヒタギをフォローする
よろず便利帖

コメント

  1. さやすへ より:

    こんにちは。更新日時順にリネームしたいと思い検索したところ、こちらのサイトでコードを拝見させていただきました。

    windows11 python3.9環境でコードを実行したところ、
    line 57, in
    times, paths = zip(*temporal_list)
    ValueError: not enough values to unpack (expected 2, got 0)
    とErrorが出てしまい実行できませんでした。何が原因と考えられるのでしょうか?
    アドバイスいただければ幸いです。

    • ジョー・ヒタギ より:

      さやすへさん
      コメントありがとうございます。
      temporal_listが空なのかもしれません。ext_list内の拡張子を持つファイルは処理対象のフォルダ内にありますでしょうか?temporal_listの中身と共に一度ご確認いただけると幸いです。

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