Python入门之shutil模块
shutil模块提供了大量的文件的高级操作。特别针对文件拷贝和删除,主要功能为目录和文件操作以及压缩操作。对单个文件的操作也可参见os模块。
注意即便是更高级别的文件复制函数(shutil.copy(),shutil.copy2())也不能复制所有文件的元数据。这意味着在POSIX平台上,文件的所有者和组以及访问控制列表都将丢失。在Mac OS中资源fork和其他元数据无法使用。这意味着资源将丢失,文件类型和创建者代码将不正确。在Windows上,文件所有者,ACL和备用数据流不会被复制。
功能:高级文件操作。类型:标准模块相关模块: os 标准模块。zipfile 标准模块。tarfile 标准模块。
1、shutil.copyfileobj(fsrc, fdst[, length]):复制文件内容(不包含元数据)从类文件对象src到类文件对dst。可选参数length指定缓冲区的大小,负数表示一次性读入。默认会把数据切分成小块拷贝,以免占用太多内存。注意:拷贝是从fsrc的当前文件开始;若如果dst存在,则会被覆盖
#!/usr/bin/env python3 import shutil import os print(os.system("cat /tmp/shutil_new.txt")) #打印出未复制内容前的文件 print("*"*60) shutil.copyfileobj(open("/tmp/shutil_old.txt","r"),open("/tmp/shutil_new.txt","w"),10) print(os.system("cat /tmp/shutil_new.txt")) #打印被复制后的文件 执行结果: [root@localhost 20170712]# ./shutil_cpobj.py 0 ************************************************************ \S Kernel \r on an \m 0
2、shutil.copyfile(src,dst):将src复制为dst;dst必须是完整的目标文件并且具有可写权限,否则将抛出异常;如果src和dst是同一个文件,将抛出shutil.Error;如果dst已存在,将会被覆盖;特殊文件,如字符或块设备、管道不能使用此功能,因为copyfile会打开并阅读文件,src和dst是字符串形式的路径。
2.1 正常复制
#!/usr/bin/env python3 import shutil import os os.system("ls /tmp/shutil_file") #查看目录/tmp/shutil_file内容 shutil.copyfile("/tmp/shutil_file/shutil_old.txt","/tmp/shutil_file/shutil_new.txt") #将文件shutil_old.txt复制shutil_new.txt print("*"*60) os.system("cat /tmp/shutil_file/shutil_new.txt") #打印被复制的文件内容 执行结果: [root@localhost 20170717]# cat /tmp/shutil_file/shutil_old.txt #查看源文件内容 Welcome to the Linux world Now we start learning python [root@localhost 20170717]# ./shutil_cpfile.py shutil_old.txt ************************************************************ Welcome to the Linux world Now we start learning python
2.2 目标文件存在复制
#!/usr/bin/env python3 import shutil import os os.system("cat /tmp/shutil_file/shutil_exist.txt") #查看存在的文件内容 shutil.copyfile("/tmp/shutil_file/shutil_new.txt","/tmp/shutil_file/shutil_exist.txt") #将shutil_new.txt文件复制为存在的文件shutil_exist.txt print("*"*60) os.system("cat /tmp/shutil_file/shutil_exist.txt") #查看复制后的文件shutil_exist.txt的内容 执行结果: [root@localhost 20170717]# ./shutil_cp_exist_file.py You don't want to learn python ************************************************************ Welcome to the Linux world Now we start learning python
2.3 存在文件不具有写权限复制
[root@localhost 20170717]# ll /tmp/shutil_file/shutil_exist.txt -r--r--r--. 1 root root 56 Jun 27 05:30 /tmp/shutil_file/shutil_exist.txt
#!/usr/bin/env python3 import shutil import os shutil.copyfile("/tmp/shutil_file/shutil_new.txt","/tmp/shutil_file/shutil_exist.txt") print("*"*60) os.system("cat /tmp/shutil_file/shutil_exist.txt") 执行结果: [chengd@localhost 20170717]$ ./shutil_cp_exist_file.py Traceback (most recent call last): File "./shutil_cp_exist_file.py", line 6, in <module> shutil.copyfile("/tmp/shutil_file/shutil_new.txt","/tmp/shutil_file/shutil_exist.txt") File "/usr/local/lib/python3.6/shutil.py", line 121, in copyfile with open(dst, 'wb') as fdst: PermissionError: [Errno 13] Permission denied: '/tmp/shutil_file/shutil_exist.txt'
注:在root用户下,无论文件是否具有写权限,root都可以写入文件。
2.4 src和dst是同一个文件
#!/usr/bin/env python3 import shutil import os shutil.copyfile("/tmp/shutil_file/shutil_old.txt","/tmp/shutil_file/shutil_old.txt") os.system("cat /tmp/shutil_file/shutil_old.txt") 执行结果: [root@localhost 20170717]# ./shutil_cpsame.py Traceback (most recent call last): File "./shutil_cpsame.py", line 6, in <module> shutil.copyfile("/tmp/shutil_file/shutil_old.txt","/tmp/shutil_file/shutil_old.txt") File "/usr/local/lib/python3.6/shutil.py", line 104, in copyfile raise SameFileError("{!r} and {!r} are the same file".format(src, dst)) shutil.SameFileError: '/tmp/shutil_file/shutil_old.txt' and '/tmp/shutil_file/shutil_old.txt' are the same file
3、shutil.copymode(src,dst):仅拷贝权限;内容、组、用户均不变;dst目标文件要存在
[root@localhost 20170717]# ls -al /tmp/shutil_cpmode* -rwxrwxrwx. 1 root root 0 Jun 27 05:46 /tmp/shutil_cpmode1.txt -rw-rw-r--. 1 chengd chengd 0 Jun 27 05:47 /tmp/shutil_cpmode2.txt
#!/usr/bin/env python3 import shutil import os os.system("ls -al /tmp/shutil_cpmode*") shutil.copymode("/tmp/shutil_cpmode1.txt","/tmp/shutil_cpmode2.txt") mode = "mode拷贝分割线" print("\n{:*^60}\n".format(mode)) os.system("ls -al /tmp/shutil_cpmode*") 执行结果: [root@localhost 20170717]# ./shutil_cpmode.py -rwxrwxrwx. 1 root root 0 Jun 27 05:46 /tmp/shutil_cpmode1.txt -rw-rw-r--. 1 chengd chengd 0 Jun 27 05:47 /tmp/shutil_cpmode2.txt *************************mode拷贝分割线************************** -rwxrwxrwx. 1 root root 0 Jun 27 05:46 /tmp/shutil_cpmode1.txt -rwxrwxrwx. 1 chengd chengd 0 Jun 27 05:47 /tmp/shutil_cpmode2.txt
4、shutil.copystat(src,dst):复制权限、最后访问时间、最后修改时间等
5、shutil.copy(src,dst):拷贝文件和权限;如果dst是目录的话,则会在dst目录中创建和src同名的文件且权限一致。
5.1 正常拷贝文件,即dst是文件
#!/usr/bin/env python3 import shutil import os os.system("ls -al /tmp/shutil_cpmode*") shutil.copy("/tmp/shutil_cpmode2.txt","/tmp/shutil_cpmode.txt") #将shutil_cpmode2.txt拷贝为shutil_cpmode.txt mode = "copy拷贝分割线" print("\n{:*^60}\n".format(mode)) os.system("ls -al /tmp/shutil_cpmode*") 执行结果: [root@localhost 20170717]# ./shutil_cp.py -rwxrwxrwx. 1 root root 0 Jun 27 05:46 /tmp/shutil_cpmode1.txt -rwxrwxrwx. 1 chengd chengd 0 Jun 27 05:47 /tmp/shutil_cpmode2.txt *************************copy拷贝分割线************************** -rwxrwxrwx. 1 root root 0 Jun 27 05:46 /tmp/shutil_cpmode1.txt -rwxrwxrwx. 1 chengd chengd 0 Jun 27 05:47 /tmp/shutil_cpmode2.txt -rwxrwxrwx. 1 root root 0 Jun 27 06:29 /tmp/shutil_cpmode.txt #拷贝文件权限未变
5.2 拷贝目标dst是目录
[root@localhost 20170717]# ll /root/tmp_dir/ total 0
#!/usr/bin/env python3 import shutil import os shutil.copy("/tmp/shutil_cpmode2.txt","/root/tmp_dir") #dst是目录的拷贝;会在dst目录中创建和shutil_cpmode2.txt同名的文件且权限一致 os.system("ls -Al /root/tmp_dir") 执行结果: [root@localhost 20170717]# ./shutil_cpdir.py total 0 -rwxrwxrwx. 1 root root 0 Jun 27 06:42 shutil_cpmode2.txt
6、shutil.copy2:类似shutil.copy,不过会将元数据也复制,实际上先调用shutil.copy,然后使用copystat。这类似于linux命令cp -p
#!/usr/bin/env python3 import shutil import os os.system("ls -al /tmp/shutil_cpmode*") shutil.copy2("/tmp/shutil_cpmode2.txt","/tmp/shutil_cp2mode.txt") #通过copy2将shutil_cpmode2.txt拷贝为shutil_cp2mode.txt mode = "copy2拷贝分割线" print("\n{:*^60}\n".format(mode)) os.system("ls -al /tmp/shutil_cp*") 执行结果: [root@localhost 20170717]# ./shutil_cp2.py -rwxrwxrwx. 1 root root 0 Jun 27 05:46 /tmp/shutil_cpmode1.txt -rwxrwxrwx. 1 chengd chengd 0 Jun 27 05:47 /tmp/shutil_cpmode2.txt -rwxrwxrwx. 1 root root 0 Jun 27 06:29 /tmp/shutil_cpmode.txt *************************copy2拷贝分割线************************** -rwxrwxrwx. 1 root root 0 Jun 27 05:47 /tmp/shutil_cp2mode.txt -rwxrwxrwx. 1 root root 0 Jun 27 05:46 /tmp/shutil_cpmode1.txt -rwxrwxrwx. 1 chengd chengd 0 Jun 27 05:47 /tmp/shutil_cpmode2.txt -rwxrwxrwx. 1 root root 0 Jun 27 06:29 /tmp/shutil_cpmode.txt
7、shutil.copytree(src_dir,dst_dir,symlinks=False,ignore=None):递归拷贝目录文件
symlinks=False:若是True时,复制时保持文件夹下的符号链接,若为False则在复制时在文件下生成物理副本来替换符号链接;默认False
shutil.ignore_patterns(*patterns):shutil.copytree的辅助函数,可以通过正则指定不拷贝那些文件;
[root@localhost 20170717]# ll /tmp/ total 68 drwxr-xr-x. 2 root root 149 Jun 26 18:01 20170704 drwxr-xr-x. 2 root root 42 Jun 26 21:08 20170706 drwxr-xr-x. 2 root root 144 Jun 27 00:08 20170707 drwxr-xr-x. 2 root root 24 Jun 27 00:45 20170708 drwxr-xr-x. 2 root root 139 Jun 27 04:52 20170712 drwxr-xr-x. 2 root root 197 Jun 27 07:10 20170717 -rw-r--r--. 1 root root 45 Jun 27 04:07 book.txt lrwxrwxrwx. 1 root root 11 Jun 27 07:04 passwd.txt -> /etc/passwd drwxr-xr-x. 3 root root 35 Jun 26 11:43 py_test1 -rwxr-xr-x. 1 root root 266 Jun 26 14:34 pytest10.py -rwxr-xr-x. 1 root root 405 Jun 26 14:17 pytest11.py -rwxr-xr-x. 1 root root 321 Jun 26 14:42 pytest12.py -rwxr-xr-x. 1 root root 348 Jun 26 14:48 pytest13.py -rwxr-xr-x. 1 root root 150 Jun 26 15:08 pytest14.py -rwxr-xr-x. 1 root root 71 Jun 26 15:17 pytest15.py -rwxr-xr-x. 1 root root 146 Jun 26 11:16 pytest1.py -rwxr-xr-x. 1 root root 54 Jun 26 11:21 pytest2.py -rwxr-xr-x. 1 root root 112 Jun 26 11:36 pytest4.py -rwxr-xr-x. 1 root root 196 Jun 26 11:43 pytest5.py -rwxr-xr-x. 1 root root 140 Jun 26 11:51 pytest6.py -rwxr-xr-x. 1 root root 545 Jun 26 13:11 pytest7.py -rwxr-xr-x. 1 root root 395 Jun 26 13:30 pytest8.py -rwxr-xr-x. 1 root root 81 Jun 26 13:34 pytest9.py -rwxr-xr-x. 1 root root 230 Jun 26 11:10 pytest.py -rwxrwxrwx. 1 root root 0 Jun 27 05:47 shutil_cp2mode.txt -rwxrwxrwx. 1 root root 0 Jun 27 05:46 shutil_cpmode1.txt -rwxrwxrwx. 1 chengd chengd 0 Jun 27 05:47 shutil_cpmode2.txt -rwxrwxrwx. 1 root root 0 Jun 27 06:29 shutil_cpmode.txt drwxr-xr-x. 2 root root 74 Jun 27 05:27 shutil_file -rw-r--r--. 1 root root 54 Jun 27 03:33 user.txt
#!/usr/bin/env python3 import shutil import os shutil.copytree("/tmp","/mnt/tmp_bak",ignore=shutil.ignore_patterns("*.py")) mode = "copytree拷贝分割线" print("\n{:*^60}\n".format(mode)) os.system("ls -Al /mnt/tmp_bak") 执行结果: [root@localhost 20170717]# ./shutil_cptree.py ***********************copytree拷贝分割线************************ total 12 drwxr-xr-x. 2 root root 6 Jun 26 18:01 20170704 drwxr-xr-x. 2 root root 6 Jun 26 21:08 20170706 drwxr-xr-x. 2 root root 6 Jun 27 00:08 20170707 drwxr-xr-x. 2 root root 6 Jun 27 00:45 20170708 drwxr-xr-x. 2 root root 6 Jun 27 04:52 20170712 drwxr-xr-x. 2 root root 6 Jun 27 07:09 20170717 -rw-r--r--. 1 root root 45 Jun 27 04:07 book.txt drwxrwxrwt. 2 root root 6 Jun 26 15:37 .font-unix drwxrwxrwt. 2 root root 6 Jun 26 15:37 .ICE-unix -rw-r--r--. 1 root root 1088 Jun 27 05:36 passwd.txt drwxr-xr-x. 3 root root 35 Jun 26 11:43 py_test1 -rwxrwxrwx. 1 root root 0 Jun 27 05:47 shutil_cp2mode.txt -rwxrwxrwx. 1 root root 0 Jun 27 05:46 shutil_cpmode1.txt -rwxrwxrwx. 1 root root 0 Jun 27 05:47 shutil_cpmode2.txt -rwxrwxrwx. 1 root root 0 Jun 27 06:29 shutil_cpmode.txt drwxr-xr-x. 2 root root 74 Jun 27 05:27 shutil_file drwxrwxrwt. 2 root root 6 Jun 26 15:37 .Test-unix -rw-r--r--. 1 root root 54 Jun 27 03:33 user.txt drwxrwxrwt. 2 root root 6 Jun 26 15:37 .X11-unix drwxrwxrwt. 2 root root 6 Jun 26 15:37 .XIM-unix
[root@localhost 20170717]# ll /mnt/tmp_bak/ total 12 drwxr-xr-x. 2 root root 6 Jun 26 18:01 20170704 drwxr-xr-x. 2 root root 6 Jun 26 21:08 20170706 drwxr-xr-x. 2 root root 6 Jun 27 00:08 20170707 drwxr-xr-x. 2 root root 6 Jun 27 00:45 20170708 drwxr-xr-x. 2 root root 6 Jun 27 04:52 20170712 drwxr-xr-x. 2 root root 6 Jun 27 07:09 20170717 -rw-r--r--. 1 root root 45 Jun 27 04:07 book.txt -rw-r--r--. 1 root root 1088 Jun 27 05:36 passwd.txt drwxr-xr-x. 3 root root 35 Jun 26 11:43 py_test1 -rwxrwxrwx. 1 root root 0 Jun 27 05:47 shutil_cp2mode.txt -rwxrwxrwx. 1 root root 0 Jun 27 05:46 shutil_cpmode1.txt -rwxrwxrwx. 1 root root 0 Jun 27 05:47 shutil_cpmode2.txt -rwxrwxrwx. 1 root root 0 Jun 27 06:29 shutil_cpmode.txt drwxr-xr-x. 2 root root 74 Jun 27 05:27 shutil_file -rw-r--r--. 1 root root 54 Jun 27 03:33 user.txt
8、shutil.rmtree(path[,ignore_errors[,onerror]]):递归的删除文件
[root@localhost 20170717]# ll /mnt/tmp_bak/ total 12 drwxr-xr-x. 2 root root 6 Jun 26 18:01 20170704 drwxr-xr-x. 2 root root 6 Jun 26 21:08 20170706 drwxr-xr-x. 2 root root 6 Jun 27 00:08 20170707 drwxr-xr-x. 2 root root 6 Jun 27 00:45 20170708 drwxr-xr-x. 2 root root 6 Jun 27 04:52 20170712 drwxr-xr-x. 2 root root 6 Jun 27 07:09 20170717 -rw-r--r--. 1 root root 45 Jun 27 04:07 book.txt -rw-r--r--. 1 root root 1088 Jun 27 05:36 passwd.txt drwxr-xr-x. 3 root root 35 Jun 26 11:43 py_test1 -rwxrwxrwx. 1 root root 0 Jun 27 05:47 shutil_cp2mode.txt -rwxrwxrwx. 1 root root 0 Jun 27 05:46 shutil_cpmode1.txt -rwxrwxrwx. 1 root root 0 Jun 27 05:47 shutil_cpmode2.txt -rwxrwxrwx. 1 root root 0 Jun 27 06:29 shutil_cpmode.txt drwxr-xr-x. 2 root root 74 Jun 27 05:27 shutil_file -rw-r--r--. 1 root root 54 Jun 27 03:33 user.txt
#!/usr/bin/env python3 import shutil import os shutil.rmtree("/mnt/tmp_bak") #递归删除/mnt下的tmp_bak中的所有文件,包含tmp_bak目录本身 mode = "rmtree拷贝分割线" print("\n{:*^60}\n".format(mode)) os.system("ls -Al /mnt/tmp_bak") 执行结果: [root@localhost 20170717]# ./shutil_rmtree.py ************************rmtree拷贝分割线************************* ls: cannot access /mnt/tmp_bak: No such file or directory #/mnt/tmp_bak已被删除
9、shutil.move(src,dst):递归的去移动文件,其实就是重命名;类似linux中的mv。
#!/usr/bin/env python3 import shutil import os os.system("ls -Al /tmp") shutil.move("/tmp/book.txt","/tmp/books.txt") mode = "move拷贝分割线" print("\n{:*^60}\n".format(mode)) os.system("ls -Al /tmp") 执行结果: [root@localhost 20170717]# ./shutil_move.py total 3 -rw-r--r--. 1 root root 45 Jun 27 04:07 book.txt drwxrwxrwt. 2 root root 6 Jun 26 15:37 .font-unix drwxrwxrwt. 2 root root 6 Jun 26 15:37 .ICE-unix*************************move拷贝分割线************************** total 3 -rw-r--r--. 1 root root 45 Jun 27 04:07 books.txt drwxrwxrwt. 2 root root 6 Jun 26 15:37 .font-unix drwxrwxrwt. 2 root root 6 Jun 26 15:37 .ICE-unix
10、shutil.make_archive(base_name, format,...):打包压缩文件
格式:shutil.make_archive(base_name, format[, root_dir[, base_dir, verbose, dry_run, owner, group, logger])
base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
root_dir: 要压缩的文件夹路径(默认当前目录)
owner: 用户,默认当前用户
group: 组,默认当前组
logger: 用于记录日志,通常是logging.Logger对象
#!/usr/bin/env python3 import shutil import os shutil.make_archive("/mnt/tmp","gztar",root_dir="/tmp") #将/tmp目录打包并压缩存放至/mnt下名为tmp mode = "archive拷贝分割线" print("\n{:*^60}\n".format(mode)) os.system("ls -Al /mnt") 执行结果: [root@localhost 20170717]# ./shutil_archive.py ************************archive拷贝分割线************************ total 8 -rw-r--r--. 1 root root 6930 Jun 27 08:19 tmp.tar.gz
11、shutil.unpack_archive(filename, extract_dir=None, format=None):解压缩归档文件
filename是存档的名称。
extract_dir是解压缩目标目录的名称。如果没有提供,则使用当前的工作目录。
format是归档格式:“zip”、“tar”或“gztar”。或任何其他已注册的格式。如果没有提供,unpackarchive将使用文件扩展名。
如果没有找到,则会增加一个ValueError。
#!/usr/bin/env python3 import shutil import os shutil.unpack_archive("/mnt/tmpbak0718.tar.gz","/mnt/tmp20170718","gztar") mode = "unpack_archive拷贝分割线" print("\n{:*^60}\n".format(mode)) os.system("ls -Al /mnt") 执行结果: [root@localhost 20170718]# ./shutil_unarchive.py ************************unpack_archive拷贝分割线************************ total 28 drwxrwxrwt. 16 lzy lzy 4096 Jun 27 08:35 tmp20170718 -rw-r--r--. 1 root root 6947 Jun 27 08:36 tmpbak0718.tar.gz -rw-r--r--. 1 root root 6920 Jun 27 08:33 tmpbak.tar.gz -rw-r--r--. 1 root root 6912 Jun 27 08:32 tmp.tar.gz
***********************************************************
学习永远不晚。——高尔基
***********************************************************

浙公网安备 33010602011771号