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