前沿:在之前的博客分享中,已经分享了 Python–使用线程–批量文件的移动 关于两层文件的移动和复制,但是如果我们想多层的复制例如:D:\department_data_management 里边的而且包含很多曾文件夹,我们想原封不动的复制到F盘,此时怎么搞?
今天就分享一下代码,使用技术:线程+队列。
# @Time : 2019-04-11 09:59
# @Author : xgp
# @File : file_move.py
# @Software: PyCharm
# @description:把整个文件夹以及子文件夹复制到某个位置。
"""
waring:当你复制的文件比较少的时候,可能因为文件夹只有一个线程在执行,而文件的复制是很多线程在执行,
这样可能导致文件夹未建立而文件却在复制而报错,这个时候建议在执行一次即可。所以此方法适合复制大量的文件,或者文件夹。
"""
import os
import shutil
import threading
from queue import Queue
class FileMove:
def __init__(self):
"""
一些参数的输入
"""
self.folder_queue = Queue()
self.file_queue = Queue()
self.method = input('请选择文件是选择 复制 还是移动 ?eg:[复制,移动]:')
self.file_path = input(r'请输入想要操作的文件夹eg:[D:\Image]:')
self.d_path = input(r'请输入想要 移动\复制 到的盘符或者路径eg:[E:, E:\image,F:,F:\image\picture]:')
self.s_path = self.file_path[:2]
def write_info(self, file_path):
"""
向队列中写入文件夹和文件
:param file_path:
:return:
"""
try:
all_folder = os.listdir(file_path)
except FileNotFoundError as e:
print('请正确输入文件夹的位置.......')
else:
for each_file in all_folder:
if os.path.isdir(os.path.join(file_path, each_file)):
self.folder_queue.put(os.path.join(file_path, each_file))
elif os.path.isfile(os.path.join(file_path, each_file)):
self.file_queue.put(os.path.join(file_path, each_file))
def read_folder(self):
"""
获取到文件夹,并在目的盘 建立文件夹,如果文件夹中还含有文件夹和文件 调用 write_info 方法继续写。
:return:
"""
while True:
try:
folder_path = self.folder_queue.get(timeout=3)
self.folder_queue.task_done()
except BaseException as e:
print('文件夹的获取结束,开始下一个阶段文件的复制............... %s' % str(e))
break
else:
try:
if not os.path.exists(folder_path.replace(self.file_path, self.d_path)):
os.makedirs(folder_path.replace(self.file_path, self.d_path))
except BaseException as e:
print('创建文件夹的时候出现了问题 %s' % str(e))
self.write_info(folder_path)
def read_file(self):
"""
从file队列中拿到文件 并进行复制或者移动。
:return:
"""
while True:
try:
file_path = self.file_queue.get(timeout=3)
self.file_queue.task_done()
except BaseException as e:
print('获取文件结束,整个流程走完.........终止 %s' % str(e))
break
else:
try:
if not os.path.exists(file_path.replace(self.file_path, self.d_path)): # 这个是你需要修改的
if self.method == "复制":
print('复制中..........')
shutil.copy(file_path, file_path.replace(self.file_path, self.d_path))
elif self.method == "移动":
print('移动中.........')
shutil.move(file_path, file_path.replace(self.file_path, self.d_path))
shutil.rmtree(self.file_path)
else:
print('暂未开放此功能........敬请期待')
break
else:
print('已经存在了')
pass
except BaseException as e:
print('复制文件的时候出错了...............%s' % str(e))
def run(self):
"""
主逻辑开始运行。
:return:
"""
thread_list = []
info_list = threading.Thread(target=self.write_info, args=(self.file_path,))
thread_list.append(info_list)
folder_list = threading.Thread(target=self.read_folder)
thread_list.append(folder_list)
for i in range(50):
file_list = threading.Thread(target=self.read_file)
thread_list.append(file_list)
for t in thread_list:
t.setDaemon(True)
t.start()
for q in [self.folder_queue, self.file_queue]:
q.join()
print('结束')
if __name__ == '__main__':
file_move = FileMove()
file_move.run()
这只是一个简单的 复制 和移动,你也可以在源代码的基础上进行修改和添加,使其功能更强,当然你也可以打包一下分享给你的朋友使用,如果运行代码中出现一点小bug自行解决或者一起讨论。