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和文件操作的一些模块,如下略做记录,方便后续查询。
参考: