python全局字符串替换脚本(包括文件内容,文件夹名,文件名)

有时候需要进行整个文件夹的字符替换(包括文件夹名、文件名、文件内容)的字符替换,如果通过手工来做太费体力,这时我们就可以用到python的脚本。

1 替换脚本

脚本参考1 《使用python进行文本替换》,略修改优化,chname.py 如下:

脚本中用到了递归算法。

#!/usr/bin/env python3
import os
import chardet
import time
import sys
 
class replace:
    path = ""
    dict_repalce = {}
    tuple_notreplace = ()
    
    def __init__(self, p, ex, d, t):
        self.path = p
        self.exclude_path = ex
        self.dict_replace = d
        self.tuple_notreplace = t
    
    def replace(self):
        ex = os.path.basename(self.path)
        if ex in self.exclude_path:
            return;
        li_os = os.listdir(self.path)            # 返回一个文件(文件夹)的列表
        for every_dir in li_os:
            filePath = os.path.join(self.path, every_dir)
            if os.path.isdir(filePath):          # 如果是一个文件夹
                print(filePath, "这是一个文件夹")
                filename = os.path.basename(filePath)
                bool_change = False              #判断文件夹名是否更改的标志
                for key in self.dict_replace.keys(): # 循环查看key
                    if key in filename:              # 查看key是不是存在文件名的一部分
                        filename_new = filename.replace(key, self.dict_replace[key])
                        bool_change = True
                if bool_change == True:              #判断文件夹名是否需要修改
                    print(f"{filename} -> {filename_new} 正在修改文件夹名...")
                    filename_new = os.path.dirname(filePath) + os.sep + filename_new
                    os.rename(filePath, filename_new) #修改文件夹名
                    print(filename_new, "文件夹名修改成功。")
                    filePath = filename_new
                replace(filePath, self.exclude_path, self.dict_replace, self.tuple_notreplace).replace()

            elif os.path.isfile(filePath):           # 判断是不是一个文件
                print(filePath, "这是一个文件")
                filename = os.path.basename(filePath)
                filename_li = filename.split('.')  #分割,防止在修改文件名的时候把文件格式后缀一起修改了
                bool_change = False                #判断文件名是否更改的标志
                for key in self.dict_replace.keys():  # 循环查看key
                    if key in filename_li[0]:         # 查看key是不是存在文件名的一部分
                        filename_li[0] = filename_li[0].replace(key, self.dict_replace[key])
                        bool_change = True
                if bool_change == True:               #判断文件名是否需要修改
                    filename_new = '.'.join(filename_li)
                    print(f"{filename} -> {filename_new} 正在修改文件名...")
                    filename_new = os.path.dirname(filePath) + os.sep + filename_new
                    os.rename(filePath, filename_new) #修改文件名
                    print(filename_new, "文件名修改成功。")
                    filePath = filename_new

                for notreplace in self.tuple_notreplace:   # 循环不能更改内容的元组
                    if os.path.basename(filePath).endswith(notreplace):
                        break
                else:
                    print(filePath, "正在修改文件内容...")
                    code = chardet.detect(open(filePath, 'rb').read())['encoding']
                    with open(filePath, encoding = code) as f:
                        file_str = f.read()
                    for key in self.dict_replace.keys():   # 循环查看key
                        if key in file_str:                # 查看key是不是存在文件名的一部分
                            file_str = file_str.replace(key, self.dict_replace[key])
                    with open(filePath, 'w', encoding = code) as f:
                        f.write(file_str)
                        print(filePath, "文件内容修改完成。")
             
if __name__=="__main__":
    path = sys.argv[1]    # 处理路径
    exclude_dir = {'.git'}
    dict_replace ={'a':"ZQQ",'c':'GG'} # 需要替换字符串的字典
    tuple_notreplace = ('.png','.pptx','.xlsx','.docx','jpg', '.pdf') #不替换内容的元组
    re = replace(path, exclude_dir, dict_replace, tuple_notreplace)
    start = time.perf_counter()
    re.replace()
    end = time.perf_counter()
    print ("程序运行时间:", end - start)

或者:使用Python os.walk() 方法(内嵌递归),my_chname.py逻辑比较简单。

import os
import chardet
import time
import sys
 
class replace:
    def __init__(self, p, ex, d, t):
        self.path = p
        self.exclude_path = ex
        self.dict_replace = d
        self.tuple_notreplace = t
    
    def replace(self):
        file_list = []
        dir_list = []
        '''
        os.walk(path) 参数:
        root保存的就是当前遍历的文件夹的绝对路径;
        dirs保存当前文件夹下的所有子文件夹的名称(仅一层,孙子文件夹不包括)
        files保存当前文件夹下的所有文件的名称
        '''
        for root, dirs, files in os.walk(self.path, topdown = True):   # 将满足条件的文件/文件夹放入列表
            dirs[:] = [d for d in dirs if d not in self.exclude_path]
            files = [file for file in files if os.path.splitext(file)[1] not in self.tuple_notreplace]
            for name in files:
                file_list.append(os.path.join(root, name))
            for name in dirs:
                dir_list.append(os.path.join(root, name))

        for f in file_list:
            if os.path.isfile(f):                                    # 处理文件内容
                print(f, "这是一个文件")

                print(f, "文件内容正在修改...")
                code = chardet.detect(open(f, 'rb').read())['encoding']
                with open(f, errors='ignore', encoding = code) as ff:
                    file_str = ff.read()
                for key in self.dict_replace.keys():                  # 循环查看key
                    if key in file_str:                               # 查看key是不是存在文件名的一部分
                        file_str = file_str.replace(key, self.dict_replace[key])
                with open(f, 'w', encoding = code) as ff:
                    ff.write(file_str)
                    print(f, "文件内容修改完成。")
                
                filename = os.path.basename(f)                       # 处理文件名
                filename_li = filename.split('.')                    # 分割,防止在修改文件名的时候把文件格式后缀一起修改了
                print(f'filename is {filename}')
                bool_change = False
                for key in self.dict_replace.keys():                 # 循环查看key
                    if key in filename_li[0]:                        # 查看key是不是存在文件名的一部分
                        filename_li[0] = filename_li[0].replace(key, self.dict_replace[key])
                        bool_change = True
                if bool_change == True:                              # 判断文件名是否需要修改
                    filename = '.'.join(filename_li)
                    print(filename, "正在修改文件名...")
                    os.rename(f, os.path.dirname(f) + os.sep + filename)  # 修改文件名
                    print(filename,"修改文件名成功。") 
        
        dir_list = dir_list[ : : -1]                         # 很重要,将根节点放到最后处理。
        for f in dir_list:
            print(f, "这是一个文件夹")
            if os.path.isdir(f):                              # 处理文件夹名
                filename = os.path.basename(f)
                bool_change = False                           #判断文件名是否更改的标志
                for key in self.dict_replace.keys():                  # 循环查看key
                    if key in filename:                               # 查看key是不是存在文件名的一部分
                        filename_new = filename.replace(key, self.dict_replace[key])
                        bool_change = True
                if bool_change == True:      #判断文件名是否被修改
                    print(filename, "正在修改文件夹名...")
                    os.rename(f, os.path.dirname(f) + os.sep + filename_new)
                    print(filename_new, "文件夹名修改成功。")
                    
if __name__=="__main__":
    path = sys.argv[1]    # 处理路径
    exclude_dir = {'.git'}
    dict_replace ={'a':"ZQQ",'c':'GG'} # 需要替换字符串的字典
    tuple_notreplace = ('.png','.pptx','.xlsx','.docx','jpg', '.pdf') #不替换内容的元组
    re = replace(path, exclude_dir, dict_replace, tuple_notreplace)
    start = time.perf_counter()
    re.replace()
    end = time.perf_counter()
    print ("程序运行时间:", end - start)

脚本涉及到os.path和文件操作的一些模块,如下略做记录,方便后续查询。

参考:

  1. 使用python进行文本替换(包括替换文件名、文件夹名、文本名)
posted @ 2022-08-07 18:33  sureZ_ok  阅读(924)  评论(0编辑  收藏  举报