遍历目录时移动重命名文件的更简洁方法
Cleaner way to move renamed files when walking over directory
我创建了一个脚本来遍历我的目录并将我的音乐文件移动到我的音乐文件夹,同时使用正则表达式库重命名文件以检查文件是否已编号(因为我发现这很烦人)。该脚本似乎工作正常,因为我没有遇到任何错误,但我想知道是否有更简洁的方法来执行此操作,因为这似乎有点令人费解且不 pythonic。 (努力编写更清晰的代码)。通过 cleaner,我并不是要任何人重写我的整个代码块,而是 check_names 函数及其在移动文件时的实现。如果还有其他错误,ose 将有助于指出以下原因。
如果这是糟糕的代码,我为任何 python "sins" 道歉,因为我之前只使用过几次 os 和正则表达式模块。
由于我正在学习如何使用这些并且目前还没有什么经验osure,解释为什么会大大有助于我的理解。所有 os.path.join(....)
都是我尝试使其成为 cross-platform 而不必硬编码路径。我说这似乎有点令人费解的原因是由于运行时它需要大约 1-2 分钟才能在 6-7 个文件夹上执行以下操作:
将压缩的 .zip
存档解压到我的原始目录中遍历这些,如果需要重命名文件,最后移动它们然后返回原始目录并删除移动的残余,或者这是正常的运行时对于正在发生的一切? (档案约为 100-300 mb)
相关函数是。
def check_names(dirpath, file_name):
check = False
new_name = None
first_check = re.compile("^\d\d - ").match(file_name)
second_check = re.compile("^\d\d ").match(file_name)
if first_check != None or second_check != None:
check = True
if first_check:
new_name = file_name[first_check.span()[1]:]
shutil.move(os.path.join(dirpath, file_name),
os.path.join(dirpath, new_name))
else:
new_name = file_name[second_check.span()[1]:]
shutil.move(os.path.join(dirpath, file_name),
os.path.join(dirpath, new_name))
return check, new_name
def move_music(source, destination, file_extension, sub_string):
source_dir = os.path.split(source)[-1]
for dirpath, dirnames, filenames in os.walk(source):
for a_file in filenames:
if (a_file.endswith(file_extension) and sub_string in a_file):
check = check_names(dirpath, a_file)
dir_name = os.path.split(dirpath)[-1]
if dir_name != source_dir:
check_folders(destination, dir_name)
if os.path.join(source, dir_name) not in COPIED_DIRECTORIES:
COPIED_DIRECTORIES.append(os.path.join(source, dir_name))
shutil.move(os.path.join(dirpath, a_file if not check[0] else check[1]),
os.path.join(destination , dir_name))
else:
shutil.move(os.path.join(dirpath, a_file if not check[0] else check[1]), destination)
要事第一:
您可以打破这样的任务并显着提高可读性。
旧:
if first_check:
new_name = file_name[first_check.span()[1]:]
shutil.move(os.path.join(dirpath, file_name),
os.path.join(dirpath, new_name))
else:
new_name = file_name[second_check.span()[1]:]
shutil.move(os.path.join(dirpath, file_name),
os.path.join(dirpath, new_name))
新:
if first_check:
new_name = file_name[first_check.span()[1]:]
else:
new_name = file_name[second_check.span()[1]:]
shutil.move(os.path.join(dirpath, file_name),
os.path.join(dirpath, new_name))
您只是在 if/else 语句中将 file_name 更改为 new_name,您不需要在 if/then 语句中进行长函数调用。
接下来,定义您的全局变量:
FIRST_CHECK = re.compile("^\d\d - ")
SECOND_CHECK = re.compile("^\d\d ")
接下来,正则表达式匹配会自动触发 if 语句,因此您可以删除:
if first_check != None:
替换为:
if first_check:
下一步是重构您的代码:您的第二个函数又长又笨重。分开来。将 move_music 更改为 2 个函数:
def move_music(source_dir, destination, dirpath, a_file):
check = check_names(dirpath, a_file)
dir_name = os.path.split(dirpath)[-1]
if dir_name != source_dir:
check_folders(destination, dir_name)
if os.path.join(source, dir_name) not in COPIED_DIRECTORIES:
COPIED_DIRECTORIES.append(os.path.join(source, dir_name))
shutil.move(os.path.join(dirpath, a_file if not check[0] else check[1]),
os.path.join(destination , dir_name))
else:
shutil.move(os.path.join(dirpath, a_file if not check[0] else check[1]), destination)
def check_move(source, destination, file_extension, sub_string):
source_dir = os.path.split(source)[-1]
for dirpath, dirnames, filenames in os.walk(source):
for a_file in filenames:
if (a_file.endswith(file_extension) and sub_string in a_file):
move_music(source_dir, destination, dirpath, a_file)
接下来,您的每行代码长度太长:将您自己的文档语句限制在 72 个字符,实际代码为 79 个字符。这增强了可读性:编码人员还能如何在分屏文本编辑器上查看您的代码?
您可以通过分解冗余语句并进一步重组代码来部分做到这一点:
def get_old_file(check, a_file):
if not check[0]:
old_file = a_file
else:
old_file = check[1]
return old_file
这是您的结束代码:您还需要完成工作!评论它并添加文档字符串。
已编辑,感谢@leewangzhong,他正确地指出了正则表达式缓存,并且由于我们只使用了 2 个正则表达式,所以我们不需要担心显式编译。
def check_names(dirpath, file_name):
check = False
new_name = None
first_check = re.match("^\d\d - ", file_name)
second_check = re.match("^\d\d ", file_name)
if first_check or second_check:
check = True
if first_check:
new_name = file_name[first_check.span()[1]:]
else:
new_name = file_name[second_check.span()[1]:]
old_path = os.path.join(dirpath, file_name)
new_path = os.path.join(dirpath, new_name)
shutil.move(old_path, new_path)
return check, new_name
def get_old_file(check, a_file):
if not check[0]:
old_file = a_file
else:
old_file = check[1]
return old_file
def move_music(source_dir, destination, dirpath, a_file):
check = check_names(dirpath, a_file)
dir_name = os.path.split(dirpath)[-1]
if dir_name != source_dir:
check_folders(destination, dir_name)
if os.path.join(source, dir_name) not in COPIED_DIRECTORIES:
path = os.path.join(source, dir_name)
COPIED_DIRECTORIES.append(path)
old_file = get_old_file(check, a_file)
old_path = os.path.join(dirpath, old_file)
new_path = os.path.join(destination , dir_name)
shutil.move(old_path, new_path)
else:
old_file = get_old_file(check, a_file)
old_path = os.path.join(dirpath, old_file)
shutil.move(old_path, destination)
def check_move(source, destination, file_extension, sub_string):
source_dir = os.path.split(source)[-1]
for dirpath, dirnames, filenames in os.walk(source):
for a_file in filenames:
if (a_file.endswith(file_extension)
and sub_string in a_file):
move_music(source_dir, destination, dirpath, a_file)
我创建了一个脚本来遍历我的目录并将我的音乐文件移动到我的音乐文件夹,同时使用正则表达式库重命名文件以检查文件是否已编号(因为我发现这很烦人)。该脚本似乎工作正常,因为我没有遇到任何错误,但我想知道是否有更简洁的方法来执行此操作,因为这似乎有点令人费解且不 pythonic。 (努力编写更清晰的代码)。通过 cleaner,我并不是要任何人重写我的整个代码块,而是 check_names 函数及其在移动文件时的实现。如果还有其他错误,ose 将有助于指出以下原因。
如果这是糟糕的代码,我为任何 python "sins" 道歉,因为我之前只使用过几次 os 和正则表达式模块。
由于我正在学习如何使用这些并且目前还没有什么经验osure,解释为什么会大大有助于我的理解。所有 os.path.join(....)
都是我尝试使其成为 cross-platform 而不必硬编码路径。我说这似乎有点令人费解的原因是由于运行时它需要大约 1-2 分钟才能在 6-7 个文件夹上执行以下操作:
将压缩的 .zip
存档解压到我的原始目录中遍历这些,如果需要重命名文件,最后移动它们然后返回原始目录并删除移动的残余,或者这是正常的运行时对于正在发生的一切? (档案约为 100-300 mb)
相关函数是。
def check_names(dirpath, file_name):
check = False
new_name = None
first_check = re.compile("^\d\d - ").match(file_name)
second_check = re.compile("^\d\d ").match(file_name)
if first_check != None or second_check != None:
check = True
if first_check:
new_name = file_name[first_check.span()[1]:]
shutil.move(os.path.join(dirpath, file_name),
os.path.join(dirpath, new_name))
else:
new_name = file_name[second_check.span()[1]:]
shutil.move(os.path.join(dirpath, file_name),
os.path.join(dirpath, new_name))
return check, new_name
def move_music(source, destination, file_extension, sub_string):
source_dir = os.path.split(source)[-1]
for dirpath, dirnames, filenames in os.walk(source):
for a_file in filenames:
if (a_file.endswith(file_extension) and sub_string in a_file):
check = check_names(dirpath, a_file)
dir_name = os.path.split(dirpath)[-1]
if dir_name != source_dir:
check_folders(destination, dir_name)
if os.path.join(source, dir_name) not in COPIED_DIRECTORIES:
COPIED_DIRECTORIES.append(os.path.join(source, dir_name))
shutil.move(os.path.join(dirpath, a_file if not check[0] else check[1]),
os.path.join(destination , dir_name))
else:
shutil.move(os.path.join(dirpath, a_file if not check[0] else check[1]), destination)
要事第一:
您可以打破这样的任务并显着提高可读性。
旧:
if first_check:
new_name = file_name[first_check.span()[1]:]
shutil.move(os.path.join(dirpath, file_name),
os.path.join(dirpath, new_name))
else:
new_name = file_name[second_check.span()[1]:]
shutil.move(os.path.join(dirpath, file_name),
os.path.join(dirpath, new_name))
新:
if first_check:
new_name = file_name[first_check.span()[1]:]
else:
new_name = file_name[second_check.span()[1]:]
shutil.move(os.path.join(dirpath, file_name),
os.path.join(dirpath, new_name))
您只是在 if/else 语句中将 file_name 更改为 new_name,您不需要在 if/then 语句中进行长函数调用。
接下来,定义您的全局变量:
FIRST_CHECK = re.compile("^\d\d - ")
SECOND_CHECK = re.compile("^\d\d ")
接下来,正则表达式匹配会自动触发 if 语句,因此您可以删除:
if first_check != None:
替换为:
if first_check:
下一步是重构您的代码:您的第二个函数又长又笨重。分开来。将 move_music 更改为 2 个函数:
def move_music(source_dir, destination, dirpath, a_file):
check = check_names(dirpath, a_file)
dir_name = os.path.split(dirpath)[-1]
if dir_name != source_dir:
check_folders(destination, dir_name)
if os.path.join(source, dir_name) not in COPIED_DIRECTORIES:
COPIED_DIRECTORIES.append(os.path.join(source, dir_name))
shutil.move(os.path.join(dirpath, a_file if not check[0] else check[1]),
os.path.join(destination , dir_name))
else:
shutil.move(os.path.join(dirpath, a_file if not check[0] else check[1]), destination)
def check_move(source, destination, file_extension, sub_string):
source_dir = os.path.split(source)[-1]
for dirpath, dirnames, filenames in os.walk(source):
for a_file in filenames:
if (a_file.endswith(file_extension) and sub_string in a_file):
move_music(source_dir, destination, dirpath, a_file)
接下来,您的每行代码长度太长:将您自己的文档语句限制在 72 个字符,实际代码为 79 个字符。这增强了可读性:编码人员还能如何在分屏文本编辑器上查看您的代码?
您可以通过分解冗余语句并进一步重组代码来部分做到这一点:
def get_old_file(check, a_file):
if not check[0]:
old_file = a_file
else:
old_file = check[1]
return old_file
这是您的结束代码:您还需要完成工作!评论它并添加文档字符串。
已编辑,感谢@leewangzhong,他正确地指出了正则表达式缓存,并且由于我们只使用了 2 个正则表达式,所以我们不需要担心显式编译。
def check_names(dirpath, file_name):
check = False
new_name = None
first_check = re.match("^\d\d - ", file_name)
second_check = re.match("^\d\d ", file_name)
if first_check or second_check:
check = True
if first_check:
new_name = file_name[first_check.span()[1]:]
else:
new_name = file_name[second_check.span()[1]:]
old_path = os.path.join(dirpath, file_name)
new_path = os.path.join(dirpath, new_name)
shutil.move(old_path, new_path)
return check, new_name
def get_old_file(check, a_file):
if not check[0]:
old_file = a_file
else:
old_file = check[1]
return old_file
def move_music(source_dir, destination, dirpath, a_file):
check = check_names(dirpath, a_file)
dir_name = os.path.split(dirpath)[-1]
if dir_name != source_dir:
check_folders(destination, dir_name)
if os.path.join(source, dir_name) not in COPIED_DIRECTORIES:
path = os.path.join(source, dir_name)
COPIED_DIRECTORIES.append(path)
old_file = get_old_file(check, a_file)
old_path = os.path.join(dirpath, old_file)
new_path = os.path.join(destination , dir_name)
shutil.move(old_path, new_path)
else:
old_file = get_old_file(check, a_file)
old_path = os.path.join(dirpath, old_file)
shutil.move(old_path, destination)
def check_move(source, destination, file_extension, sub_string):
source_dir = os.path.split(source)[-1]
for dirpath, dirnames, filenames in os.walk(source):
for a_file in filenames:
if (a_file.endswith(file_extension)
and sub_string in a_file):
move_music(source_dir, destination, dirpath, a_file)