Python的高级文件操作(shutil模块)

                                      作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

 

   如果让我们用python的文件处理来进行文件拷贝,想必很多小伙伴的思路是:使用打开2个文件对象,源文件读取内容,写入目标文件中来完成拷贝过程。但是这样丢失stat数据信息(权限)等,因为根本没有复制这些信息过去。那目录复制又这咋办呢?

  Python提供了一个方便的库shutil(高级文件操作)。它可以解决上面提到的问题,接下来我们来一起学习。

 

一.复制

1>.copyfilobj

 1 #!/usr/bin/env python
 2 #_*_conding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie
 5 
 6 import shutil
 7 
 8 src_file = r"E:\temp\a.txt"
 9 dest_file = r"E:\temp\a.txt-1"
10 
11 #写入测试数据
12 with open(src_file,"w",encoding="utf8") as f:
13     f.write("尹正杰到此一游!")
14 
15 with open(src_file,"r",encoding="utf8") as f1:
16     with open(dest_file,"w") as f2:
17         """
18             文件对象的复制,f1和f2是open函数打开的文件对象,仅复制内容。后面的length指定了表示buffer的大小。这个长度咱们
19         可以不指定,因为该函数有默认值,即"16*1024",建议使用IDE查看源码
20         """
21         shutil.copyfileobj(f1,f2,length=4096)             
22         print("文件拷贝成功")
23 
24 
25 
26 #以上代码输出结果如下:
27 文件拷贝成功

2>.copyfile

 1 #!/usr/bin/env python
 2 #_*_conding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie
 5 
 6 import shutil
 7 
 8 src_file = r"E:\temp\a.txt"
 9 dest_file = r"E:\temp\a.txt-2"
10 
11 #写入测试数据
12 with open(src_file,"w",encoding="utf8") as f:
13     f.write("尹正杰到此一游!")
14 
15 with open(src_file,"r") as f1:
16     with open(dest_file,"w") as f2:
17         shutil.copyfile(src_file,dest_file)             #复制文件内容,不含元数据。本质上调用的就是copyfileobj,所以不带元数据内容复制。
18         print("文件拷贝成功")
19         
20         
21         
22 #以上代码输出结果如下:
23 文件拷贝成功

3>.copymode

 1 #!/usr/bin/env python
 2 #_*_conding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie
 5 
 6 import shutil,os
 7 
 8 src_file = r"E:\temp\a.txt"
 9 dest_file = r"E:\temp\a.txt-1"
10 
11 print(os.stat(src_file))
12 print(os.stat(dest_file))
13 
14 shutil.copymode(src_file,dest_file)         #仅仅复制权限,该方法在Linux系统看起来比较直观
15 
16 print(os.stat(src_file))
17 print(os.stat(dest_file))

4>.copystat

 1 #!/usr/bin/env python
 2 #_*_conding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie
 5 
 6 import shutil,os
 7 
 8 src_file = r"E:\temp\a.txt"
 9 dest_file = r"E:\temp\a.txt-1"
10 
11 print(os.stat(src_file))
12 print(os.stat(dest_file))
13 
14 shutil.copystat(src_file,dest_file)         #复制元数据,stat包含权限
15 
16 print(os.stat(src_file))
17 print(os.stat(dest_file))

5>.copy

 1 #!/usr/bin/env python
 2 #_*_conding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie
 5 
 6 import shutil,os
 7 
 8 src_file = r"E:\temp\a.txt"
 9 dest_file = r"E:\temp\a.txt-1"
10 
11 print(os.stat(src_file))
12 print(os.stat(dest_file))
13 
14 """
15     复制文件内容,权限和部分元数据,不包括创建时间和修改时间。本质上调用的是copyfile和copymode方法,可以使用IDE查看源码
16 """
17 shutil.copy(src_file,dest_file)          
18 
19 print(os.stat(src_file))
20 print(os.stat(dest_file))

6>.copy2

 1 #!/usr/bin/env python
 2 #_*_conding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie
 5 
 6 import shutil,os
 7 
 8 src_file = r"E:\temp\a.txt"
 9 dest_file = r"E:\temp\a.txt-3"
10 
11 print(os.stat(src_file))
12 print(os.stat(dest_file))
13 
14 """
15    copy2比copy多了复制全部元数据,但需要平台支持。本质上调用的是copyfile和copystat函数。
16 """
17 shutil.copy2(src_file,dest_file)
18 
19 print(os.stat(src_file))
20 print(os.stat(dest_file))

7>.copytree

 1 #!/usr/bin/env python
 2 #_*_conding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie
 5 
 6 import shutil,os
 7 
 8 src_file = r"E:\temp\test"
 9 dest_file = r"E:\temp\bak"
10 
11 
12 def my_ignore(src,names):
13     ig = filter(lambda x:x.startswith("a"),names)
14     return set(ig)
15 
16 """
17    递归复制目录。默认使用copy2,也就是带更多的元数据复制。
18    函数签名为:
19         def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,ignore_dangling_symlinks=False)
20         其中src,dst必须都是目录,src必须存在,dst必须不存在。
21         ignore = func,提供一个"callable(src, names) -> ignored_names"。提供一个函数,提供一个函数,它会被调用。src是源目录,
22     names是os.listdir(src)的结果,就是列出src中的文件名,返回值要被过滤的文件名的set类型数据。
23 """
24 shutil.copytree(src_file,dest_file,ignore=my_ignore)

 

二.删除

 1 #!/usr/bin/env python
 2 #_*_conding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie
 5 
 6 import shutil
 7 
 8 dest_file = r"E:\temp\bak"
 9 
10 """
11     递归删除,如果Linux的"rm -rf"一样危险,慎用哈。
12     它不是原子性操作,有可能删除错误,就会中断,已经删除的就删除啦。
13     其函数签名为:
14         def rmtree(path, ignore_errors=False, onerror=None)
15         其中ignore_errors为True就表示忽略vuow,当为Flase或者omitted时onerror生效。
16         onerror为callable接受函数function,path和execinofie。
17 """
18 shutil.rmtree(dest_file)            #删除的目标目录必须存在哟!否则会抛出异常的~

 

三.移动

 1 #!/usr/bin/env python
 2 #_*_conding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie
 5 
 6 import shutil
 7 
 8 src_file = r"E:\temp\test\a.txt"
 9 dest_file = r"E:\temp\test\b.txt"
10 
11 
12 """
13     递归移动文件,目录到目标,返回目标。
14     本身使用的时os.rename方法,这个在源码中可以看到。
15     如果不支持rename,如果时目录则copytree再删除源目录。
16     默认使用copy2方法。
17 """
18 shutil.move(src_file,dest_file)

 

四.小试牛刀

  shutil还有打包功能,生成tar并压缩。支持压缩格式有zip,gz,bz,xz。如果有需要的小伙伴可以自行查阅一下源码的实现方式,我这里就不罗嗦了。

  下面有几个可以使用shutil模块的案例,仅供参考。

1>.指定一个源文件,实现copy到目标目录。

例如:
  把/tmp/test.txt 拷贝到 /tmp/test.txt-bak
 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:https://www.cnblogs.com/yinzhengjie
 5 #EMAIL:y1053419035@qq.com
 6 
 7 
 8 from os import path
 9 
10 basedir = "/tmp/"
11 
12 src = "test.txt"
13 
14 dst = "test.txt-bak"
15 
16 src = path.join(basedir,src)
17 
18 dst = path.join(basedir,dst)
19 
20 #写入测试内容
21 with open(src,"w",encoding="utf-8") as f:
22     f.writelines("\n".join(("yinzhengjie","jason","https://www.cnblogs.com/yinzhengjie")))
23 
24 #自定函数实现文件复制
25 def copy(src,dst):
26     with open(src,"rb") as f1:
27         with open(dst,"wb") as f2:
28             length = 16 * 1024
29             while True:
30                 buffer = f1.read(length)       #需要注意的是,这里需要一个缓冲区。
31                 if not buffer:
32                     break
33                 f2.write(buffer)
34 
35 #调用咱们自定义的函数
36 copy(src,dst)
自定函数实现文件复制

相关文章: