Python shutil模块
shutil模块下 copy(复制)、rm(删除)、move(移动) 常用方法举例。
copyfileobj(fsrc, fdst[, length])
copyfile(src, dst, *, follow_symlinks=True)
copymode(src, dst, *, follow_symlinks=True)
copystat(src, dst, *, follow_symlinks=True)
copy(src, dst, *, follow_symlinks=True)
copy2(src, dst, *, follow_symlinks=True)
copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,ignore_dangling_symlinks=False)
rmtree(path, ignore_errors=False, onerror=None)
move(src, dst, copy_function=copy2)
shutil模块(高级文件操作)
copy (复制)
copyfileobj(fsrc, fdst[, length])
文件对象的复制,fsrc和fdst是open打开的文件对象,复制内容。fdst要求可写。
length指定了表示buffer的大小
源码:
def copyfileobj(fsrc, fdst, length=16*1024): """copy data from file-like object fsrc to file-like object fdst""" while 1: buf = fsrc.read(length) if not buf: break fdst.write(buf)
只要传入的src文件不为空,就把读取的内容写入dst
举例:
In [11]: with open('test1','w') as f1: ...: f1.write('hello\nPython') ...: In [13]: with open('test1','a+') as f1: ...: f1.write('\nMagedu') ...: f1.flush() ...: f1.seek(0) ...: with open('test2','w') as f2: ...: shutil.copyfileobj(f1,f2) ...:
copyfile
复制文件内容,不含元信息。src、dst必须为文件的路径字符串,而不是 _io.TextIOWrapper
本质上调用的就是copyfileobj,二进制内容复制
源码主要部分:
def copyfile(src, dst, *, follow_symlinks=True): ..... with open(src, 'rb') as fsrc: with open(dst, 'wb') as fdst: copyfileobj(fsrc, fdst) ......
举例:
In [6]: shutil.copyfile('test1','test2') Out[6]: 'test2' In [7]: ll 总用量 32 -rw-rw-r-- 1 python 5 10月 28 11:50 test1 -rw-rw-r-- 1 python 5 10月 28 11:51 test2
copymode
仅仅复制权限
举例:
In [8]: os.chmod('test2',0o600) In [9]: ll 总用量 32 -rw-rw-r-- 1 python 5 10月 28 11:50 test1 -rw------- 1 python 5 10月 28 11:51 test2 In [10]: shutil.copymode('test2','test1') In [11]: ll 总用量 32 -rw------- 1 python 5 10月 28 11:50 test1 -rw------- 1 python 5 10月 28 11:51 test2
copystat
复制元数据及权限
举例:
In [12]: os.chmod('test1',0o666) #修改test1权限为666 In [13]: ll -rw-rw-rw- 1 python 5 10月 28 11:50 test1 -rw------- 1 python 5 10月 28 11:51 test2 In [14]: !stat test1 #test1元信息 文件:"test1" 大小:5 块:8 IO 块:4096 普通文件 设备:fd00h/64768d Inode:1423520 硬链接:1 权限:(0666/-rw-rw-rw-) Uid:( 1000/ python) Gid:( 1000/ python) 最近访问:2017-10-28 11:50:59.727245005 +0800 最近更改:2017-10-28 11:50:47.415746323 +0800 最近改动:2017-10-28 11:56:12.610665000 +0800 创建时间:- In [15]: !stat test2 #test2元信息与test1不同 文件:"test2" 大小:5 块:8 IO 块:4096 普通文件 设备:fd00h/64768d Inode:1423521 硬链接:1 权限:(0600/-rw-------) Uid:( 1000/ python) Gid:( 1000/ python) 最近访问:2017-10-28 11:51:29.014500749 +0800 最近更改:2017-10-28 11:51:29.014500749 +0800 最近改动:2017-10-28 11:53:37.444865005 +0800 创建时间:- In [16]: shutil.copystat('test1','test2') #copy元信息及权限 In [17]: !stat test1 #对比拷贝后的权限及元信息 文件:"test1" 大小:5 块:8 IO 块:4096 普通文件 设备:fd00h/64768d Inode:1423520 硬链接:1 权限:(0666/-rw-rw-rw-) Uid:( 1000/ python) Gid:( 1000/ python) 最近访问:2017-10-28 11:50:59.727245005 +0800 最近更改:2017-10-28 11:50:47.415746323 +0800 最近改动:2017-10-28 11:56:12.610665000 +0800 创建时间:- In [18]: !stat test2 #拷贝后的test2元信息和权限和test1一致 文件:"test2" 大小:5 块:8 IO 块:4096 普通文件 设备:fd00h/64768d Inode:1423521 硬链接:1 权限:(0666/-rw-rw-rw-) Uid:( 1000/ python) Gid:( 1000/ python) 最近访问:2017-10-28 11:50:59.727245005 +0800 最近更改:2017-10-28 11:50:47.415746323 +0800 最近改动:2017-10-28 11:57:01.582474472 +0800 创建时间:-
copy
复制文件内容、权限和部分元数据,不包括创建时间和修改时间。
follow_symlinks为False时,不跟随源文件中的符号链接
本质上调用的就是:
copyfile(src, dst, follow_symlinks=follow_symlinks)
copymode(src, dst, follow_symlinks=follow_symlinks)
源码:
def copy(src, dst, *, follow_symlinks=True): ...... if os.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) return dst
copy2
copy2比copy多了复制全部元数据:权限、属主属组、时间戳等信息
本质上也是调用:
copyfile(src, dst, follow_symlinks=follow_symlinks)
copystat(src, dst, follow_symlinks=follow_symlinks)
copytree
本身就是一个递归函数,递归复制目录。默认调用copy2(src,dst),也就是带更多的元数据复制。
src、dst必须时目录,src必须存在,dst必须不存在
ignore = func,提供一个callable(src,names) -> ignored_names。提供一个函数,它会被调用。src是源目录。names是os.listdir(src)的结果,就是列出src中的文件名,返回值是要被过滤的文件名的set类型数据
举例:
忽略以t开头的文件:
In [37]: def ignore_t(src,names): ...: ig = filter(lambda x: x.startswith('t'),names) ...: return set(ig) ...: In [38]: shutil.copytree('/home/python/magedu/project/cmdb/','/home/python/magedu/project/cmdb-bak/',ignore=ignore_t) Out[38]: '/home/python/magedu/project/cmdb-bak/' In [39]: !tree /home/python/magedu/project/cmdb /home/python/magedu/project/cmdb ├── log ├── test1 ├── test2 ├── WordCount1.py └── WordCount.py 1 directory, 4 files In [40]: !tree /home/python/magedu/project/cmdb-bak /home/python/magedu/project/cmdb-bak ├── log ├── WordCount1.py └── WordCount.py 1 directory, 2 files
忽略所有目录,只拷贝文件:
In [28]: def ig_t(dir,files): ...: import os ...: return [f for f in files if os.path.isfile(os.path.join(dir,f))] #如果是文件类型就做为函数返回值返回 ...: In [29]: shutil.copytree('/home/python/magedu/project/cmdb/','/home/python/magedu/project/cmdb-bak/',ignore=ig_t) Out[29]: '/home/python/magedu/project/cmdb-bak/' In [30]: !tree /home/python/magedu/project/cmdb /home/python/magedu/project/cmdb ├── log ├── test1 ├── test2 ├── WordCount1.py └── WordCount.py 1 directory, 4 files In [31]: !tree /home/python/magedu/project/cmdb-bak /home/python/magedu/project/cmdb-bak └── log 1 directory, 0 files
rm删除
rmtree
递归删除目录(类似rm -rf,谨慎操作)
举例:
In [41]: shutil.rmtree('/home/python/magedu/project/cmdb-bak') In [42]: !tree /home/python/magedu/project/cmdb-bak /home/python/magedu/project/cmdb-bak [error opening dir] 0 directories, 0 files In [43]: !tree /home/python/magedu/project/ /home/python/magedu/project/ ├── cmdb │ ├── log │ ├── test1 │ ├── test2 │ ├── WordCount1.py │ └── WordCount.py ├── cmdb_bak │ ├── log │ ├── test1 │ ├── test2 │ ├── WordCount1.py │ └── WordCount.py └── django 5 directories, 8 files
move移动
move(src, dst, copy_function=copy2)
递归移动文件、目录到目标,返回目标。本身使用的是os.rename方法。
os.rename
os.rename(src, dst, *, src_dir_fd=None, dst_dir_fd=None)
举例:
In [45]: os.rename('WordCount.py','/home/python/magedu/project/django/WordCount2.py') In [46]: !tree /home/python/magedu/project/ /home/python/magedu/project/ ├── cmdb │ ├── log │ ├── test1 │ ├── test2 │ └── WordCount1.py ├── cmdb_bak │ ├── log │ ├── test1 │ ├── test2 │ ├── WordCount1.py │ └── WordCount.py └── django └── WordCount2.py # 5 directories, 8 files