小能豆

python os.renames 造成混乱的结果

py

我想使用它们自己的元数据重命名 mp3 文件并对它们进行排序(有/没有元数据),并在他执行语句时获得粗略的结果和奇怪的 FileNotFound 错误(图片如下)

粗略结果-> 两首歌曲中的一首被正确重命名,但另一首歌曲有自己的标题分割,而一部分是名称的一部分,另一部分有点像新的子目录!?

错误-> FileNotFoundError: [WinError 2]

Python代码,非常短

print("Start")

    tracks = []
    tracksMeta = []
    tracksNoMeta = []

    source = os.path.join(os.getcwd(), "testSongs") #os.getcwd()
    dest = os.path.join(source, "ohneMeta")
    destM = os.path.join(source, "mitMeta")

    print(source)
    print(dest)
    print(destM)
    print(os.path.exists(source))
    print(os.path.exists(dest))
    print(os.path.exists(destM))



    if not os.path.exists(dest):
        os.makedirs(dest)
    if not os.path.exists(destM):
        os.makedirs(destM)

    for root, dirs, files, in os.walk(source):
        for index, name in enumerate(files):
            if name.endswith((".mp3",".m4a",".flac",".alac")):
                tracks.append(name)
                try:

                    temp_track = TinyTag.get(root + "\\" + name)

                    #metadata available
                    if temp_track.title and temp_track.artist:
                        print(index, name, "->", temp_track.artist, "-", temp_track.title)
                        tracksMeta.append(name + "->" + temp_track.title + "-" + temp_track.artist)

                    #rename
                        if os.access(source, os.W_OK):
                            print(temp_track.title)
                            print(temp_track.artist)

                            newname = temp_track.title + " - " + temp_track.artist + ".mp3"
                            if os.path.exists(source) and os.path.exists(destM):
                                os.renames(os.path.join(source, name), os.path.join(destM, newname))

                    #or not
                    else:
                        tracksNoMeta.append(name)
                    #move
                        if os.path.exists(source) and os.path.exists(dest):
                            os.renames(os.path.join(source, name), os.path.join(dest, name))

                except TinyTagException:
                    print("Error")

阅读 56

收藏
2025-03-14

共1个答案

小能豆

你的代码的问题可能有几个原因,特别是 FileNotFoundError: [WinError 2] 和错误的文件路径。下面是一些可能的改进建议,以避免你的错误:


问题分析

  1. os.renames() 可能导致意外的目录创建
  2. os.renames() 不仅会重命名文件,还会尝试创建必要的目录。这可能会导致某些文件路径错误,比如 newname 变量可能包含非法字符(如 :/ 等),导致文件变成目录。
  3. 解决方案:使用 os.rename() 而不是 os.renames()

  4. 路径拼接问题

  5. 代码中的 root + "\\" + name 可能导致 FileNotFoundError,建议使用 os.path.join(root, name) 以确保正确拼接路径。

  6. 文件名可能包含非法字符

  7. Windows 不允许某些字符,如 :?*,在文件名中。你需要在 newname 之前进行合法性检查。

  8. os.access(source, os.W_OK) 可能不适用于 Windows

  9. 在 Windows 上,即使 os.access(source, os.W_OK) 返回 True,仍然可能无法重命名文件,因为文件可能被其他进程占用。

修改后的代码

import os
import re
from tinytag import TinyTag, TinyTagException

print("Start")

tracks = []
tracksMeta = []
tracksNoMeta = []

source = os.path.join(os.getcwd(), "testSongs")
dest = os.path.join(source, "ohneMeta")
destM = os.path.join(source, "mitMeta")

print(source)
print(dest)
print(destM)
print("Source exists:", os.path.exists(source))
print("Destination (no metadata) exists:", os.path.exists(dest))
print("Destination (with metadata) exists:", os.path.exists(destM))

# 确保目标目录存在
os.makedirs(dest, exist_ok=True)
os.makedirs(destM, exist_ok=True)

# 处理音频文件
for root, dirs, files in os.walk(source):
    for index, name in enumerate(files):
        if name.endswith((".mp3", ".m4a", ".flac", ".alac")):
            tracks.append(name)
            try:
                file_path = os.path.join(root, name)
                temp_track = TinyTag.get(file_path)

                # 处理元数据
                if temp_track.title and temp_track.artist:
                    print(index, name, "->", temp_track.artist, "-", temp_track.title)
                    tracksMeta.append(name + " -> " + temp_track.title + " - " + temp_track.artist)

                    # 规范化文件名(去除非法字符)
                    safe_title = re.sub(r'[<>:"/\\|?*]', '', temp_track.title)
                    safe_artist = re.sub(r'[<>:"/\\|?*]', '', temp_track.artist)
                    newname = f"{safe_title} - {safe_artist}.mp3"
                    new_path = os.path.join(destM, newname)

                    # 确保文件不存在后再重命名
                    if os.path.exists(file_path):
                        os.rename(file_path, new_path)
                        print(f"Moved: {file_path} -> {new_path}")

                else:
                    tracksNoMeta.append(name)

                    # 移动无元数据的文件
                    new_path = os.path.join(dest, name)
                    if os.path.exists(file_path):
                        os.rename(file_path, new_path)
                        print(f"Moved (no metadata): {file_path} -> {new_path}")

            except TinyTagException:
                print(f"Error reading metadata for: {name}")

print("Done.")

修正点

使用 os.rename() 代替 os.renames()
使用 os.path.join() 代替字符串拼接
处理 Windows 不允许的文件名字符
使用 os.makedirs(dest, exist_ok=True) 避免重复创建目录
添加 print() 语句调试文件移动过程

这样可以避免你的 FileNotFoundError,同时防止错误的子目录被创建。 🚀

2025-03-14