视觉艺术初学者

【原创】Python实现-Windows下批量重命名文件和文件夹

2020-04-08  本文已影响0人  复苏的兵马俑

A、基础功能:
  1、实现Windows系统下对文件和文件夹的批量重命名;
  2、可由用户输入指定的目录路径;
  3、可选择对文件、文件夹或所有对象进行重命名;
  4、重命名的类型包括删除文件/文件夹名称中的指定字符串、给文件或文件夹的名称添加指定前缀、给文件或文件夹的名称添加制定后缀。

B、进阶功能:
  1、可对指定的后缀文件进行重命名;
  2、实现通过密码认证后才能正常使用重命名程序,且输入密码时以‘*’隐藏;
  3、使用pyinstaller将该Python程序打包成Windows的exe文件。

C、打包exe:
  1、安装pyinstaller;
  2、打包命令pyinstaller -F FileRename.py

D、说明:在PyCharm中不能运行,需在Windows命令行控制台运行py文件(因使用msvcrt模块的缘故)。

代码示例:

import os
import re
import msvcrt

def get_all_file(dir_path, file_list):
    '''
    通过递归获取dir_path目录下的所有文件和文件夹的绝对路径,添加到file_list列表中,并返回。
    :param dir_path: (类型:字符串)指定目录的绝对路径
    :param file_list: (类型:列表)存放文件和文件夹绝对路径的列表
    :return: (类型:列表)返回file_list列表
    '''
    for file in os.listdir(dir_path):
        file_path = os.path.join(dir_path, file)    # 通过os.path.join()方法生成当前目录下的文件或文件夹的绝对路径
        file_list.append(file_path) # 将获取到的file_path追加到file_list列表中
        if os.path.isdir(file_path):   # 判断当前获取到的file_path是否是目录,如果是目录,则继续递归
            get_all_file(file_path, file_list)  # 递归当前获取的file_path,并传入更新后的file_list
    return file_list    # 返回file_list列表

def filename_del_str(file_names, suffix, keyword, dir_or_file):
    '''
    删除文件名或文件夹名中的指定字符串keyword。
    :param file_names: (类型:列表)指定目录下的所有文件和文件夹的绝对路径列表
    :param suffix: (类型:字符串)指定的文件后缀字符串,用于筛选出特定类型的文件进行操作
    :param keyword: (类型:字符串)指定需要删除的特定字符串
    :param dir_or_file: (类型:字符串)指定操作对象是文件还是文件夹,all-代表所有对象,file-代表文件,dir-代表目录
    :return: 无返回值
    '''
    for file in file_names:
        check = os.path.join(os.path.abspath('.'), file)
        if dir_or_file == 'all':    # 判断指定的对象是否是所有对象
            conditions = os.path.isfile(check) or os.path.isdir(check)  # 两个条件,或关系,如果该对象是文件或文件夹,则返回True,否则,则返回False,赋值给conditions
        elif dir_or_file == 'file':    # 判断指定的对象是否是文件
            conditions = os.path.isfile(check)  # 如果该对象为文件,则返回True,否则,返回False,赋值给conditions
        elif dir_or_file == 'dir':    # 判断指定的对象是否是目录
            conditions = os.path.isdir(check)  # 如果该对象为文件夹,则返回True,否则,返回False,赋值给conditions
        if conditions:
            if len(suffix)==0 or suffix.isspace():  # 判断指定的文件后缀suffix的长度是否等于0或空格,如果是,则返回True,说明没有指定特定文件类型,将对所有对象进行操作
                if keyword in file:
                    new_file = file.replace(keyword, '')    # 使用replace()将file中存在的指定字符串用空字符串替代
                    print(file, " -> ", new_file)
                    os.rename(file, new_file)   # 通过os.rename()对文件或文件夹进行重命名
                    for i in range(len(file_names)):
                        file_names[i] = file_names[i].replace(file, new_file)   # 对file_names所有对象中存在的file均使用new_file替代
            else:
                if re.match('.+?\.'+suffix+'$', file) != None and keyword in file:  # 用正则表达式匹配后缀名
                    new_file = file.replace(keyword, '')
                    print(file, " -> ", new_file)
                    os.rename(file, new_file)
                    for i in range(len(file_names)):
                        file_names[i] = file_names[i].replace(file, new_file)

def filename_add_str(file_names, suffix, keyword, location, dir_or_file):
    '''
    在文件名或文件夹名中添加指定字符串keyword。
    :param file_names: (类型:列表)指定目录下的所有文件和文件夹的绝对路径列表
    :param suffix: (类型:字符串)指定的文件后缀字符串,用于筛选出特定类型的文件进行操作
    :param keyword: (类型:字符串)指定需要删除的特定字符串
    :param location: (类型:字符串)指定给文件名或文件夹名添加前缀还是后缀,prefix-代表前缀,suffix-代表后缀
    :param dir_or_file: (类型:字符串)指定操作对象是文件还是文件夹,all-代表所有对象,file-代表文件,dir-代表目录
    :return: 无返回值
    '''
    file_names.reverse()    # 将file_names列表进行反转,此目的是为了从最内层开始对文件或文件夹进行重命名,如果从外层向内层进行操作,在执行os.rename时就会存在找不到指定路径的错误
    for file in file_names:
        check = os.path.join(os.path.abspath('.'), file)
        if dir_or_file == 'all':
            conditions = os.path.isfile(check) or os.path.isdir(check)
        elif dir_or_file == 'file':
            conditions = os.path.isfile(check)
        elif dir_or_file == 'dir':
            conditions = os.path.isdir(check)
        if conditions:
            if len(suffix) == 0 or suffix.isspace():
                if location == 'prefix':    # 判断指定的location是否为前缀,如果是,则返回True,否则为False
                    file_path = os.path.dirname(file)   # 通过os.path.dirname()获取file的目录路径,并赋值给file_path
                    base_name = os.path.basename(file)  # 通过os.path.basename()获取file的名称,并赋值给base_name
                    new_name = keyword + base_name  # 将keyword与base_name进行连接,得到新的file名称,并赋值给new_name
                    new_file = os.path.join(file_path, new_name)
                    print(file, " -> ", new_file)
                    os.rename(file, new_file)  # 通过os.rename()对文件或文件夹进行重命名
                elif location == 'suffix':    # 判断指定的location是否为后缀,如果是,则返回True,否则为False
                    file_path = os.path.dirname(file)
                    file_name, ext = os.path.splitext(file)
                    base_name = os.path.basename(file_name)
                    new_name = base_name + keyword + ext
                    new_file = os.path.join(file_path, new_name)
                    print(file, " -> ", new_file)
                    os.rename(file, new_file)
            else:
                if re.match('.+?\.' + suffix + '$', file) != None:  # 用正则表达式匹配后缀名
                    if location == 'prefix':
                        file_path = os.path.dirname(file)
                        base_name = os.path.basename(file)
                        new_name = keyword + base_name
                        new_file = os.path.join(file_path, new_name)
                        print(file, " -> ", new_file)
                        os.rename(file, new_file)
                    elif location == 'suffix':
                        file_path = os.path.dirname(file)
                        file_name, ext = os.path.splitext(file) # 通过os.path.splitext()将文件名和文件后缀切分,分别赋值给file_name和ext
                        base_name = os.path.basename(file_name)
                        new_name = base_name + keyword + ext    # 将base_name、keyword、ext进行连接,得到新的file名称,并赋值给new_name
                        new_file = os.path.join(file_path, new_name)
                        print(file, " -> ", new_file)
                        os.rename(file, new_file)

def Input_string():
    '''
    引导用户输入需要删除或添加的字符串(keyword)。
    :return: (类型:字符串)返回用户输入的字符串keyword
    '''
    flag = 1
    while flag:
        keyword = input("请输入字符串:")  # 用户输入字符串,并赋值给keyword
        if len(keyword) == 0 or keyword.isspace():
            print("字符串不能为空,请重新输入!\n")   # 判断keyword是否为空,如果为空,则提示用户重新输入
            continue    # 继续从头开始执行循环,让客户重新输入
        while True:
            '''
            让客户确认输入的字符串是否是正确的,如果正确,则输入‘Y’,如果不正确,则输入‘N’,并回到输入的位置重新输入
            输入的字母不区分大小写,直接回车代表输入'Y'
            '''
            confirm = input("请确认字符串是否为{},请回复'Y'或'N'(字母不区分大小写,直接回车代表'Y'):".format(repr(keyword))).strip()
            if confirm.upper() == 'Y' or confirm == '':
                flag = 0
                break
            elif confirm.upper() == 'N':
                print('字符串不正确,需重新输入!\n')
                break
            else:
                print('输入错误,请重新输入!\n')
                continue
    return keyword

def set_suffix():
    '''
    引导用户输入需要筛选的文件后缀(suffix)。
    :return:
    '''
    flag = 1
    while flag:
        suffix = input("\n需要筛选的文件名后缀(直接回车代表所有):")  # 用户输入字符串,并赋值给suffix,直接回车代表输入为空
        while True:
            '''
            让客户确认输入的字符串是否是正确的,如果正确,则输入‘Y’,如果不正确,则输入‘N’,并回到输入的位置重新输入
            输入的字母不区分大小写,直接回车代表输入'Y'
            三元运算符:'所有' if suffix == '' else suffix,如果suffix为空,则将‘所有’输出到指定的位置,否则,则将suffix的内容输出到指定的位置
            '''
            confirm = input("\n请确认筛选的文件名后缀是否为'{}',请回复'Y'或'N'(字母不区分大小写,直接回车代表'Y'):".format('所有' if suffix == '' else suffix)).strip()
            if confirm.upper() == 'Y' or confirm == '':
                flag = 0
                break
            elif confirm.upper() == 'N':
                print('要筛选的文件名后缀不正确,需重新输入!\n')
                break
            else:
                print('输入错误,请重新输入!\n')
                continue
    return suffix

def is_finish(flag01, flag02, flag03):
    '''
    用于执行完每一次操作之后,让用户选择是否继续执行。
    :param flag01: (类型:整型数值)第一层循环的标识
    :param flag02: (类型:整型数值)第二层循环的标识
    :param flag03: (类型:整型数值)第三层循环的标识
    :return: (类型:元组)返回由flag01、flag02、flag03组成的元组
    '''
    while True:
        is_continue = input("\n文件重命名完成!是否继续?请回复'Y'或'N'(字母不区分大小写,直接回车代表'Y'):").strip()
        if is_continue.upper() == 'Y' or is_continue == '':
            flag03 = 0  # 将第三层循环的标识赋值为0
            break
        elif is_continue.upper() == 'N':
            flag01 = 0  # 将第一层循环的标识赋值为0
            flag02 = 0  # 将第二层循环的标识赋值为0
            flag03 = 0  # 将第三层循环的标识赋值为0
            break
        else:
            print('输入错误,请重新输入!\n')
    return flag01, flag02, flag03   # 返回由flag01、flag02、flag03组成的元组

def set_dif_or_file(flag01):
    '''
    引导用户选择操作的对象是所有对象,还是文件或文件夹。
    :param flag01: (类型:整型数值)第一层循环的标识
    :return:(类型:元组)返回由flag01、dir_or_file组成的元组
    '''
    while True:
        '''
        引导用户选择操作对象
        1-代表所有对象,并将‘all’赋值给dir_or_file
        2-代表文件,并将‘file’赋值给dir_or_file
        3-代表文件夹,并将‘dir’赋值给dir_or_file
        R-代表返回上一级
        Q-代表结束程序
        '''
        dir_or_file = input('''\n选择列表如下:\n1: 所有\n2: 文件\n3: 文件夹\nR: 返回上一级\nQ: 退出\n\n请选择重命名文件还是目录(输入对应功能的编号即可,字母不区分大小写):''').strip()
        if dir_or_file == '1':
            dir_or_file = 'all'
            break
        elif dir_or_file == '2':
            dir_or_file = 'file'
            break
        elif dir_or_file == '3':
            dir_or_file = 'dir'
            break
        elif dir_or_file.upper() == 'R':
            print('返回上一级!\n')
            flag01 = -1 # 将第一层循环的标识赋值为-1
            break
        elif dir_or_file.upper() == 'Q':
            flag01 = 0 # 将第一层循环的标识赋值为0
            break
        else:
            print('输入错误,请重新输入!\n')
    return flag01, dir_or_file  # 返回由flag01、dir_or_file组成的元组

if __name__ == '__main__':
    flag01 = 1
    while flag01:   # 第一层循环
        count = 3
        flag02 = 1
        while flag02:   # 第二层循环
            flag02 = 1
            print('请输入密码:', end='', flush=True)
            password = []
            while True:   # 第三层循环
                ch = msvcrt.getch()
                # 退格
                if ch == b'\x08':
                    if password:
                        password.pop()
                        msvcrt.putch(b'\b')
                        msvcrt.putch(b' ')
                        msvcrt.putch(b'\b')
                # Esc
                elif ch == b'\x1b':
                    break
                elif ch == b'\r':
                    msvcrt.putch(b'\n')
                    password = b''.join(password).decode()
                    if password == '888888':
                        print('\n登录成功,开始运行...\n')
                        flag02 = 0
                        break
                    else:
                        count -= 1
                        if count == 0:
                            print('\n你的输入次数已用完!\n')
                            flag02 = 0
                            break
                        else:
                            print('\n你输入的密码不正确,你还有{}次输入机会,请重新输入!\n'.format(count))
                            flag02 = -1
                            break
                else:
                    password.append(ch)
                    msvcrt.putch(b'*')
        if count == 0:
            break
        elif flag02 == -1:
            continue
        flag03 = 1
        while flag03:   # 第二层循环
            if count == 0:
                break
            dir_path = input("请输入路径(输入'Q'即可退出,字母不区分大小写,直接回车代表当前路径):").strip()
            if dir_path.upper() == 'Q':
                flag01 = 0
                break
            elif dir_path == '':
                dir_path = os.getcwd()
            elif not os.path.isdir(dir_path):
                print('输入的路径不正确,请重新输入!')
                continue
            print("\n选择的路径为:'{}'".format(dir_path))
            file_list = []
            file_names = get_all_file(dir_path, file_list)

            flag01, dir_or_file = set_dif_or_file(flag01)

            if flag01 == 0:
                break
            elif flag01 == -1:
                continue

            suffix = ''
            if dir_or_file != 'dir':
                suffix = set_suffix()

            flag04 = 1
            while flag04:   # 第三层循环
                operation = input('''\n选择列表如下:\n1: 在文件名/文件夹名中删除指定的字符串\n2: 在文件名/文件夹名中增加指定的字符串\nR: 返回上一级\nQ: 退出\n\n请选择你要操作的功能(输入对应功能的编号即可,字母不区分大小写):''').strip()
                if operation == '1':
                    keyword = Input_string()
                    filename_del_str(file_names, suffix, keyword, dir_or_file)
                    flag01, flag03, flag04 = is_finish(flag01, flag03, flag04)

                elif operation == '2':
                    flag05 = 1
                    #
                    while flag05:   # 第四层循环
                        location = input('''\n选择列表如下:\n1: 在文件名/文件夹名的开头增加指定字符串\n2: 在文件名/文件夹名的结尾增加指定字符串\nR: 返回上一级\nQ: 退出程序\n\n请选择你要操作的功能(输入对应功能的编号即可,字母不区分大小写):''').strip()
                        if location == '1':
                            location = 'prefix'
                            keyword = Input_string()
                            filename_add_str(file_names, suffix, keyword, location, dir_or_file)
                            flag01, flag03, flag04 = is_finish(flag01, flag03, flag04)
                            break

                        elif location == '2':
                            location = 'suffix'
                            keyword = Input_string()
                            filename_add_str(file_names, suffix, keyword, location, dir_or_file)
                            flag01, flag03, flag04 = is_finish(flag01, flag03, flag04)
                            break

                        elif location.upper() == 'R':
                            print('返回上一级!\n')
                            break

                        elif location.upper() == 'Q':
                            flag01 = 0
                            flag03 = 0
                            flag04 = 0
                            break

                        else:
                            print('输入错误,请重新输入!\n')  #

                elif operation.upper() == 'R':
                    print('返回上一级!\n')
                    break

                elif operation.upper() == 'Q':
                    flag01 = 0
                    flag03 = 0
                    break

                else:
                    print('输入错误,请重新输入!\n')
        if flag03 == 0:
                break
    print('\n程序结束!')

  Python实现-Windows下批量重命名文件和文件夹的源文件(包括py文件和exe文件)下载链接请关注微信公众号“全栈POT修炼”,并回复“8033”获取。


“全栈POT修炼”

  转载请注明出处,原创来自于https://www.jianshu.com/p/b3331aed27ab

上一篇下一篇

猜你喜欢

热点阅读