Python中shutil模块的常用文件操作函数用法示例
os模块提供了对目录或者文件的新建/删除/查看文件属性,还提供了对文件以及目录的路径操作。比如说:绝对路径,父目录…… 但是,os文件的操作还应该包含移动复制 打包压缩解压等操作,这些os模块都没有提供。
而本文所讲的shutil则就是对os中文件操作的补充。--移动复制 打包压缩解压,
shutil函数功能:
1 shutil.copyfileobj(fsrc,fdst[,length=16*1024])
copy文件内容到另一个文件,可以copy指定大小的内容
先来看看其源代码。
defcopyfileobj(fsrc,fdst,length=16*1024): """copydatafromfile-likeobjectfsrctofile-likeobjectfdst""" while1: buf=fsrc.read(length) ifnotbuf: break fdst.write(buf)
注意!在其中fsrc,fdst都是文件对象,都需要打开后才能进行复制操作
importshutil
f1=open('name','r')
f2=open('name_copy','w+')
shutil.copyfileobj(f1,f2,length=16*1024)
2 shutil.copyfile(src,dst)
copy文件内容,是不是感觉上面的文件复制很麻烦?还需要自己手动用open函数打开文件,在这里就不需要了,事实上,copyfile调用了copyfileobj
defcopyfile(src,dst,*,follow_symlinks=True):
if_samefile(src,dst):
raiseSameFileError("{!r}and{!r}arethesamefile".format(src,dst))
forfnin[src,dst]:
try:
st=os.stat(fn)
exceptOSError:
#Filemostlikelydoesnotexist
pass
else:
#XXXWhataboutotherspecialfiles?(sockets,devices...)
ifstat.S_ISFIFO(st.st_mode):
raiseSpecialFileError("`%s`isanamedpipe"%fn)
ifnotfollow_symlinksandos.path.islink(src):
os.symlink(os.readlink(src),dst)
else:
withopen(src,'rb')asfsrc:
withopen(dst,'wb')asfdst:
copyfileobj(fsrc,fdst)
returndst
shutil.copyfile('name','name_copy_2')
#一句就可以实现复制文件内容
3 shutil.copymode(src,dst)
仅copy权限,不更改文件内容,组和用户。
defcopymode(src,dst,*,follow_symlinks=True): ifnotfollow_symlinksandos.path.islink(src)andos.path.islink(dst): ifhasattr(os,'lchmod'): stat_func,chmod_func=os.lstat,os.lchmod else: return elifhasattr(os,'chmod'): stat_func,chmod_func=os.stat,os.chmod else: return st=stat_func(src) chmod_func(dst,stat.S_IMODE(st.st_mode))
先看两个文件的权限
[root@slyoyopython_test]#ls-l total4 -rw-r--r--.1rootroot79May1405:17test1 -rwxr-xr-x.1rootroot0May1419:10test2
运行命令
>>>importshutil
>>>shutil.copymode('test1','test2')
查看结果
[root@slyoyopython_test]#ls-l total4 -rw-r--r--.1rootroot79May1405:17test1 -rw-r--r--.1rootroot0May1419:10test2
当我们将目标文件换为一个不存在的文件时报错
>>>shutil.copymode('test1','test3')
Traceback(mostrecentcalllast):
File"<stdin>",line1,in<module>
File"/usr/local/python/lib/python3.4/shutil.py",line132,incopymode
chmod_func(dst,stat.S_IMODE(st.st_mode))
FileNotFoundError:[Errno2]Nosuchfileordirectory:'test233'
4 shutil.copystat(src,dst)
复制所有的状态信息,包括权限,组,用户,时间等
defcopystat(src,dst,*,follow_symlinks=True):
def_nop(*args,ns=None,follow_symlinks=None):
pass
#followsymlinks(akadon'tnotfollowsymlinks)
follow=follow_symlinksornot(os.path.islink(src)andos.path.islink(dst))
iffollow:
#usetherealfunctionifitexists
deflookup(name):
returngetattr(os,name,_nop)
else:
#usetherealfunctiononlyifitexists
#*and*itsupportsfollow_symlinks
deflookup(name):
fn=getattr(os,name,_nop)
iffninos.supports_follow_symlinks:
returnfn
return_nop
st=lookup("stat")(src,follow_symlinks=follow)
mode=stat.S_IMODE(st.st_mode)
lookup("utime")(dst,ns=(st.st_atime_ns,st.st_mtime_ns),
follow_symlinks=follow)
try:
lookup("chmod")(dst,mode,follow_symlinks=follow)
exceptNotImplementedError:
#ifwegotaNotImplementedError,it'sbecause
#*follow_symlinks=False,
#*lchown()isunavailable,and
#*either
#*fchownat()isunavailableor
#*fchownat()doesn'timplementAT_SYMLINK_NOFOLLOW.
#(itreturnedENOSUP.)
#thereforewe'reoutofoptions--wesimplycannotchownthe
#symlink.giveup,suppresstheerror.
#(whichiswhatshutilalwaysdidinthiscircumstance.)
pass
ifhasattr(st,'st_flags'):
try:
lookup("chflags")(dst,st.st_flags,follow_symlinks=follow)
exceptOSErroraswhy:
forerrin'EOPNOTSUPP','ENOTSUP':
ifhasattr(errno,err)andwhy.errno==getattr(errno,err):
break
else:
raise
_copyxattr(src,dst,follow_symlinks=follow)
5 shutil.copy(src,dst)
复制文件的内容以及权限,先copyfile后copymode
defcopy(src,dst,*,follow_symlinks=True): ifos.path.isdir(dst): dst=os.path.join(dst,os.path.basename(src)) copyfile(src,dst,follow_symlinks=follow_symlinks) copymode(src,dst,follow_symlinks=follow_symlinks) returndst
6 shutil.copy2(src,dst)
复制文件的内容以及文件的所有状态信息。先copyfile后copystat
defcopy2(src,dst,*,follow_symlinks=True):
"""Copydataandallstatinfo("cp-psrcdst").Returnthefile's
destination."
Thedestinationmaybeadirectory.
Iffollow_symlinksisfalse,symlinkswon'tbefollowed.This
resemblesGNU's"cp-Psrcdst".
"""
ifos.path.isdir(dst):
dst=os.path.join(dst,os.path.basename(src))
copyfile(src,dst,follow_symlinks=follow_symlinks)
copystat(src,dst,follow_symlinks=follow_symlinks)
returndst
7 shutil.copytree(src,dst,symlinks=False,ignore=None,copy_function=copy2,ignore_dangling_symlinks=False)
递归的复制文件内容及状态信息
defcopytree(src,dst,symlinks=False,ignore=None,copy_function=copy2, ignore_dangling_symlinks=False): names=os.listdir(src) ifignoreisnotNone: ignored_names=ignore(src,names) else: ignored_names=set() os.makedirs(dst) errors=[] fornameinnames: ifnameinignored_names: continue srcname=os.path.join(src,name) dstname=os.path.join(dst,name) try: ifos.path.islink(srcname): linkto=os.readlink(srcname) ifsymlinks: #Wecan'tjustleaveitto`copy_function`becauselegacy #codewithacustom`copy_function`mayrelyoncopytree #doingtherightthing. os.symlink(linkto,dstname) copystat(srcname,dstname,follow_symlinks=notsymlinks) else: #ignoredanglingsymlinkiftheflagison ifnotos.path.exists(linkto)andignore_dangling_symlinks: continue #otherwiseletthecopyoccurs.copy2willraiseanerror ifos.path.isdir(srcname): copytree(srcname,dstname,symlinks,ignore, copy_function) else: copy_function(srcname,dstname) elifos.path.isdir(srcname): copytree(srcname,dstname,symlinks,ignore,copy_function) else: #WillraiseaSpecialFileErrorforunsupportedfiletypes copy_function(srcname,dstname) #catchtheErrorfromtherecursivecopytreesothatwecan #continuewithotherfiles exceptErroraserr: errors.extend(err.args[0]) exceptOSErroraswhy: errors.append((srcname,dstname,str(why))) try: copystat(src,dst) exceptOSErroraswhy: #CopyingfileaccesstimesmayfailonWindows ifgetattr(why,'winerror',None)isNone: errors.append((src,dst,str(why))) iferrors: raiseError(errors) returndst #versionvulnerabletoraceconditions
[root@slyoyopython_test]#treecopytree_test/
copytree_test/
└──test
├──test1
├──test2
└──hahaha
[root@slyoyotest]#ls-l
total0
-rw-r--r--.1pythonpython0May1419:36hahaha
-rw-r--r--.1pythonpython0May1419:36test1
-rw-r--r--.1rootroot0May1419:36test2
>>>shutil.copytree('copytree_test','copytree_copy')
'copytree_copy'
[root@slyoyopython_test]#ls-l
total12
drwxr-xr-x.3rootroot4096May1419:36copytree_copy
drwxr-xr-x.3rootroot4096May1419:36copytree_test
-rw-r--r--.1pythonpython79May1405:17test1
-rw-r--r--.1rootroot0May1419:10test2
[root@slyoyopython_test]#treecopytree_copy/
copytree_copy/
└──test
├──hahaha
├──test1
└──test2
8 shutil.rmtree(path,ignore_errors=False,onerror=None)
递归地删除文件
defrmtree(path,ignore_errors=False,onerror=None):
ifignore_errors:
defonerror(*args):
pass
elifonerrorisNone:
defonerror(*args):
raise
if_use_fd_functions:
#Whiletheunsafermtreeworksfineonbytes,thefdbaseddoesnot.
ifisinstance(path,bytes):
path=os.fsdecode(path)
#Note:Toguardagainstsymlinkraces,weusethestandard
#lstat()/open()/fstat()trick.
try:
orig_st=os.lstat(path)
exceptException:
onerror(os.lstat,path,sys.exc_info())
return
try:
fd=os.open(path,os.O_RDONLY)
exceptException:
onerror(os.lstat,path,sys.exc_info())
return
try:
ifos.path.samestat(orig_st,os.fstat(fd)):
_rmtree_safe_fd(fd,path,onerror)
try:
os.rmdir(path)
exceptOSError:
onerror(os.rmdir,path,sys.exc_info())
else:
try:
#symlinkstodirectoriesareforbidden,seebug#1669
raiseOSError("Cannotcallrmtreeonasymboliclink")
exceptOSError:
onerror(os.path.islink,path,sys.exc_info())
finally:
os.close(fd)
else:
return_rmtree_unsafe(path,onerror)
9 shutil.move(src,dst)
递归的移动文件
defmove(src,dst):
real_dst=dst
ifos.path.isdir(dst):
if_samefile(src,dst):
#Wemightbeonacaseinsensitivefilesystem,
#performtherenameanyway.
os.rename(src,dst)
return
real_dst=os.path.join(dst,_basename(src))
ifos.path.exists(real_dst):
raiseError("Destinationpath'%s'alreadyexists"%real_dst)
try:
os.rename(src,real_dst)
exceptOSError:
ifos.path.islink(src):
linkto=os.readlink(src)
os.symlink(linkto,real_dst)
os.unlink(src)
elifos.path.isdir(src):
if_destinsrc(src,dst):
raiseError("Cannotmoveadirectory'%s'intoitself'%s'."%(src,dst))
copytree(src,real_dst,symlinks=True)
rmtree(src)
else:
copy2(src,real_dst)
os.unlink(src)
returnreal_dst
10 make_archive(base_name,format,root_dir=None,base_dir=None,verbose=0,dry_run=0,owner=None,group=None,logger=None)
压缩打包
defmake_archive(base_name,format,root_dir=None,base_dir=None,verbose=0,
dry_run=0,owner=None,group=None,logger=None):
save_cwd=os.getcwd()
ifroot_dirisnotNone:
ifloggerisnotNone:
logger.debug("changinginto'%s'",root_dir)
base_name=os.path.abspath(base_name)
ifnotdry_run:
os.chdir(root_dir)
ifbase_dirisNone:
base_dir=os.curdir
kwargs={'dry_run':dry_run,'logger':logger}
try:
format_info=_ARCHIVE_FORMATS[format]
exceptKeyError:
raiseValueError("unknownarchiveformat'%s'"%format)
func=format_info[0]
forarg,valinformat_info[1]:
kwargs[arg]=val
ifformat!='zip':
kwargs['owner']=owner
kwargs['group']=group
try:
filename=func(base_name,base_dir,**kwargs)
finally:
ifroot_dirisnotNone:
ifloggerisnotNone:
logger.debug("changingbackto'%s'",save_cwd)
os.chdir(save_cwd)
returnfilename
base_name: 压缩打包后的文件名或者路径名
format: 压缩或者打包格式 "zip","tar","bztar"or"gztar"
root_dir: 将哪个目录或者文件打包(也就是源文件)
>>>shutil.make_archive('tarball','gztar',root_dir='copytree_test')
[root@slyoyopython_test]#ls-l
total12
drwxr-xr-x.3rootroot4096May1419:36copytree_copy
drwxr-xr-x.3rootroot4096May1419:36copytree_test
-rw-r--r--.1rootroot0May1421:12tarball.tar.gz
-rw-r--r--.1pythonpython79May1405:17test1
-rw-r--r--.1rootroot0May1419:10test2