问题描述
我想将文件夹和文件从源目录复制到另一个目标目录。每个目录都包含子文件夹和许多文件。
到目前为止,我尝试了以下代码,灵感来自 Stackoverflow 中的一篇文章:
import os
import shutil
root_src_dir = r'C:\....'
root_dst_dir = r'C:\....'
for src_dir,dirs,files in os.walk(root_src_dir):
dst_dir = src_dir.replace(root_src_dir,root_dst_dir,1)
if not os.path.exists(dst_dir):
os.makedirs(dst_dir)
for file_ in files:
src_file = os.path.join(src_dir,file_)
dst_file = os.path.join(dst_dir,file_)
if os.path.exists(dst_file):
# in case of the src and dst are the same file
if os.path.samefile(src_file,dst_file):
continue
os.remove(dst_file)
shutil.copy2(src_file,dst_dir)
对于相同的文件夹和文件名,此代码将目标目录与源目录等同。这可以替换目标中最新的文件夹和文件,这是一场灾难,而我希望将最新的保留在两个目录中,因为它们具有相同的文件夹和文件名。
解决方法
这是我写的程序。它是一种交互式的,还具有移动和删除功能以及复制功能。并根据扩展名过滤数据。
import os
import shutil
from os.path import join
from time import perf_counter
print('Written By : SaGaR')
print('Applies operation on all the files with specified ext. to the destination path specified:')
scandir=input('Enter the path to scan(absolute or relative path):')
print(f'You entered :{scandir}')
choice = input('Enter operation to perform(move|copy|delete|list):').lower()
EXCLUDE=['Android','DCIM','documents','WhatsApp','MIUI','bluetooth'] #exclude some system folder on android . Add your one also.
if choice == 'copy' or choice =='move':
dest=input('Enter the destination path(absolute or relative path):')
print(f'You entered :{dest}')
EXCLUDE.append(dest)
DATA_TYPES=input('Enter Data types to filter(comma-seprated)(ex.- jpg,txt): ').split(',')
files2=[]
print('*'*5,'FINDING FILES')
for root,dirs,files in os.walk(scandir):
for file in files:
for typ in DATA_TYPES:
if file.endswith(typ):
a = join(root,file)
print(root,end='')
print('-->',file)
files2.append(a)
for directory in EXCLUDE:
if directory in dirs:
dirs.remove(directory)
def copy_move_files():
start=perf_counter()
print('-'*5,f'Trying To {choice.capitalize} Files')
if not os.path.isdir(dest):
print(f'{dest} does not exists')
print(f'Creating {dest} directory')
os.mkdir(dest)
else:
print(f'{dest} exists')
for file in files2:
fpath=os.path.join(dest,os.path.split(file)[-1])
try:
if not os.path.exists(fpath):
if choice=='move':
shutil.move(file,dest)
print(f'{file.split("/")[-1]} Moved Successfully')
if choice=='copy':
shutil.copy(file,dest)
print(f'{file.split("/")[-1]} Copied Successfully')
else:
print(f'{file.split("/")[-1]} Already in destination folder')
except shutil.SameFileError:
print(f'{file.split("/")[-1].strip()} Already Exists in the destination directory. Add the Destination directory to EXCLUDE ')
end = perf_counter() - start
print(f'Operation took {end} second(s)')
def delete_files():
print('-'*5,'Trying To Delete Files')
for file in files2:
os.remove(file)
print(f'{file} deleted')
if choice == 'copy' or choice=='move':
copy_move_files()
elif choice == 'delete':
delete_files()
else:
print('No valid or "list" option detected\nOnly listing Files')
print('Exiting the program Now')
,
这是使用shutil.copytree 和my_copy 函数的解决方案。
在 my_copy 中有一个 if 语句来检查哪个是最新的文件。import os
import shutil
def my_copy(src,dst):
print(src)
print(dst)
if not os.path.exists(dst):
shutil.copy2(src,dst)
else:
if os.path.getmtime(src) > os.path.getmtime(dst):
shutil.copy2(src,dst)
return True
def rec_copy():
root_src_dir = r'C:\...'
root_dst_dir = r'C:\...'
try:
if not os.path.exists(root_dst_dir):
print(os.path.exists(root_dst_dir))
os.makedirs(root_dst_dir)
print(os.path.exists(root_dst_dir))
shutil.copytree(root_src_dir,root_dst_dir,copy_function=my_copy,dirs_exist_ok=True)
except Exception as err:
print(err)