参考文章地址:
https://segmentfault.com/a/1190000016689023
文章翻译了python标准库中shutil的介绍:
https://docs.python.org/zh-cn/3.7/library/shutil.html
shutil模块提供了一些针对文件和目录的高级操作,主要是拷贝、移动。对于单个文件的操作,还可参考os模块
Warning: 即使是高级别的拷贝函数(shutil.copy(),shutil.copy2())也不能拷贝所有的文件元数据。意思是:在POSIX系统中,文件所有者、属组以及ACL信息会丢失。在Windows平台上,文件所有者,ACL以及ADS(供选数据流)不会被复制。On Mac OS, the resource fork and other metadata are not used. This means that resources will be lost and file type and creator codes will not be correct.
复制file-like对象fsrc的内容到fdst,如果fdst不存在则自动创建。length表示缓冲大小,如果是负数表示直接复制,不循环遍历块中的源数据。数据默认按块读取(16 * 1024)避免不可控的内存消耗。
import shutil
shutil.copyfileobj(open("fsrc.txt", "rb"), open("fdst.txt", "wb"))
'''
with open("a.txt",'rb') as f_scr:
with open("b.txt",'wb') as f_des:
shutil.copyfileobj(f_scr,f_des)
'''
复制文件src的内容到dst并返回dst,如果dst不存在则自动创建。src和dst是字符串类型的路径名。
如果src和dst指向同一个文件,抛出SameFileError异常。
目标位置必须是可写的,否则将抛出OSError异常(实际抛出的PermissionError)。如果dst已经存在,则直接覆盖。特殊文件比如块设备、字符设备、管道不能使用此函数复制。
如果follow_symlinks为False且src是软链接(硬链接和软链接见上一篇文章),将创建一个新的软链接替代拷贝行为
shutil.copyfile("src.txt", "dst.txt")
将source路径下整个文件夹,包括里面到子文件夹和文件复制到destination路径下,如果destination文件夹已经存在,就会返回一个FileExistsError错误,说明每次执行该函数都会创建destination文件夹,所以在执行前要检查destination文件夹是否存在,后面到应用的例子中有解释。
复制文件src的权限位(permission bits)到dst,src和dst是字符串类型的路径名。如果follow_symlinks为False且src和dst都是软链接,将修改dst软链接文件而非源文件的权限。
此函数并非所有平台可用,如果它不能修改本地平台的软链接但又执行了相关操作,将不做任何操作直接返回None
# 修改前
-rw-r--r--. 1 root root 96 10月 11 12:26 aa.txt
-rw-------. 1 root root 1362 9月 6 22:07 anaconda-ks.cfg
-rw-------. 1 admin admin 0 10月 11 12:53 bb.txt
lrwxrwxrwx. 1 root root 21 10月 11 12:58 cc.txt -> /root/anaconda-ks.cfg
>>> shutil.copymode("aa.txt", "bb.txt")
>>> shutil.copymode("aa.txt", "cc.txt")
# 修改后
-rw-r--r--. 1 root root 96 10月 11 12:26 aa.txt
-rw-r--r--. 1 root root 1362 9月 6 22:07 anaconda-ks.cfg
-rw-r--r--. 1 admin admin 0 10月 11 12:53 bb.txt
lrwxrwxrwx. 1 root root 21 10月 11 12:58 cc.txt -> /root/anaconda-ks.cfg
复制src的权限位、最后访问时间、最后修改时间以及标志(flag)到dst,src和dst是字符串类型的路径名,可以是文件或目录。在Linux平台上还会复制扩展属性。
如果follow_symlinks为False,且src和dst都是软链接,此函数直接操作软链接而非源文件(目录)。
Note:并非所有平台都能检查和修改软链接,python能告诉用户本地平台可使用哪些功能。
复制文件src的内容和权限位到dst,dst可以是文件或目录,如果是文件,函数的返回值就是dst,如果是目录,函数的返回值就是src的文件名与dst的路径拼接。src和dst都是字符串类型,如果dst指向一个目录,则创建与src同名(basename)的新文件。
如果follow_symlinks为False,且src是软链接,dst将作为软链接创建;如果follow_symlinks为True,src为软链接,则实际拷贝的是src指向的源文件。
copy()使用copymode()拷贝权限位,使用copyfile()拷贝文件内容
>>> shutil.copy("src.txt", "dst.txt")
'dst.txt'
>>> shutil.copy("src.txt", "/tmp/")
'/tmp/src.txt'
>>> shutil.copy("src.txt", "/Dota2/") # 传入一个不存在的目录
Traceback (most recent call last):
...
IsADirectoryError: [Errno 21] Is a directory: '/Dota2/'
除了还会保留src的所有元数据(如创建时间、修改时间等),其他与copy()相同。
当follow_symlinks为False且src为软链接时,dst将作为软链接被创建并拷贝src的所有元数据到dst。
copy2()使用copystat()拷贝元数据,使用copyfile()拷贝文件内容
'''
开发环境:win10
开发工具:pycharm /python3.7
'''
from shutil import *
from pathlib import *
import re
#或者from pathlib impor WindowsPath
#或者from pathlib impor Path
#注意在同一个文件夹下面才能写成这种相对地址,否则请写文件的绝对地址
pathFile = Path('src.txt')
#打开文件src.txt,注意readlines()返回的是包含所有路径的 列表
with pathFile.open() as f:
pathlist = f.readlines()
newpath = Path.cwd()/'src/VW'
for i in pathlist:
#易错,千万要注意
#因为列表元素都是地址,后面都是换行符结尾,后面使用时会将换行符也算做地址
#就会出现错误提示:OSError:[WinError 123] 文件名,目录名,或卷标语法不正确。
# source = i.replace('/n','')
source = re.sub(r'(\s+?)$',",i)#用正则表达式将结尾处/t,/n,/r全部替换移除
usource = source.encode('utf-8')#将路径统一转为utf-8编码,防止路径中包含中文乱码
relativepath = Path(source).relative_to(Path(source).parent.parent)
destipath = newpath/relativepath
#或者destipath = newpath.joinpath(relativepath)
#但千万不能用‘+’拼接,会报错:TypeError: unsupported oprand type(s)
#for + :'WindowsPath' and 'WindowsPath'
if not destipath.exists():#这里必须判断destipath是否已经存在
#因为执行copytree函数会自动创建一个新文件夹(根据destination参数)并将source文件夹中的内容
#复制过去,现在在循环里面,每执行一次copytree函数会自动创建一个新文件夹
# 就会返回一个FileExitsError错误
copytree(usource.decode('utf-8),destipath)#将路径解码为utf-8字符串,复制文件夹