美文网首页视觉艺术初学者
【原创】Python实现-Windows下批量重命名文件和文件夹

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

作者: 复苏的兵马俑 | 来源:发表于2020-04-08 18:54 被阅读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

    相关文章

      网友评论

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

        本文链接:https://www.haomeiwen.com/subject/xfqxmhtx.html