5
5
----------
6
6
问题
7
7
----------
8
- You need to copy or move files and directories around, but you don’t want to do it by
9
- calling out to shell commands.
8
+ 你想哟啊复制或移动文件和目录,但是又不想调用shell命令。
10
9
11
10
|
12
11
13
12
----------
14
13
解决方案
15
14
----------
16
- The shutil module has portable implementations of functions for copying files and
17
- directories. The usage is extremely straightforward. For example:
15
+ ``shutil `` 模块有很多便捷的函数可以复制文件和目录。使用起来非常简单,比如:
18
16
19
- import shutil
17
+ .. code-block :: python
20
18
21
- # Copy src to dst. (cp src dst)
22
- shutil.copy(src, dst)
19
+ import shutil
23
20
24
- # Copy files, but preserve metadata (cp -p src dst)
25
- shutil.copy2 (src, dst)
21
+ # Copy src to dst. (cp src dst)
22
+ shutil.copy (src, dst)
26
23
27
- # Copy directory tree (cp -R src dst)
28
- shutil.copytree (src, dst)
24
+ # Copy files, but preserve metadata (cp -p src dst)
25
+ shutil.copy2 (src, dst)
29
26
30
- # Move src to dst (mv src dst)
31
- shutil.move(src, dst)
27
+ # Copy directory tree (cp -R src dst)
28
+ shutil.copytree(src, dst)
29
+
30
+ # Move src to dst (mv src dst)
31
+ shutil.move(src, dst)
32
+
33
+ 这些函数的参数都是字符串形式的文件或目录名。
34
+ 底层语义模拟了类似的Unix命令,如上面的注释部分。
32
35
33
- The arguments to these functions are all strings supplying file or directory names. The
34
- underlying semantics try to emulate that of similar Unix commands, as shown in the
35
- comments.
36
- By default, symbolic links are followed by these commands. For example, if the source
37
- file is a symbolic link, then the destination file will be a copy of the file the link points
38
- to. If you want to copy the symbolic link instead, supply the follow_symlinks keyword
39
- argument like this:
36
+ 默认情况下,对于符号链接而已这些命令处理的是它指向的东西。
37
+ 例如,如果源文件是一个符号链接,那么目标文件将会是符号链接指向的文件。
38
+ 如果你只想复制符号链接本身,那么需要指定关键字参数 ``follow_symlinks `` ,如下:
40
39
41
- shutil.copy2(src, dst, follow_symlinks=False)
40
+ .. code-block :: python
41
+ shutil.copy2(src, dst, follow_symlinks = False )
42
42
43
- If you want to preserve symbolic links in copied directories, do this:
43
+ 如果你想保留被复制目录中的符号链接,像这样做:
44
44
45
- shutil.copytree(src, dst, symlinks=True)
45
+ .. code-block :: python
46
46
47
- The copytree() optionally allows you to ignore certain files and directories during the
48
- copy process. To do this, you supply an ignore function that takes a directory name
49
- and filename listing as input, and returns a list of names to ignore as a result. For ex‐
50
- ample:
47
+ shutil.copytree(src, dst, symlinks = True )
51
48
52
- def ignore_pyc_files(dirname, filenames):
53
- return [name in filenames if name.endswith('.pyc')]
49
+ `` copytree() `` 可以让你在复制过程中选择性的忽略某些文件或目录。
50
+ 你可以提供一个忽略函数,接受一个目录名和文件名列表作为输入,返回一个忽略的名称列表。例如:
54
51
55
- shutil.copytree(src, dst, ignore=ignore_pyc_files)
52
+ .. code-block :: python
53
+
54
+ def ignore_pyc_files (dirname , filenames ):
55
+ return [name in filenames if name.endswith(' .pyc' )]
56
+
57
+ shutil.copytree(src, dst, ignore = ignore_pyc_files)
56
58
57
59
Since ignoring filename patterns is common, a utility function ignore_patterns() has
58
60
already been provided to do it. For example:
@@ -64,47 +66,49 @@ shutil.copytree(src, dst, ignore=shutil.ignore_patterns('*~','*.pyc'))
64
66
----------
65
67
讨论
66
68
----------
67
- Using shutil to copy files and directories is mostly straightforward. However, one
68
- caution concerning file metadata is that functions such as copy2() only make a best
69
- effort in preserving this data. Basic information, such as access times, creation times,
70
- and permissions, will always be preserved, but preservation of owners, ACLs, resource
71
- forks, and other extended file metadata may or may not work depending on the un‐
72
- derlying operating system and the user’s own access permissions. You probably wouldn’t
73
- want to use a function like shutil.copytree() to perform system backups.
74
- When working with filenames, make sure you use the functions in os.path for the
75
- greatest portability (especially if working with both Unix and Windows). For example:
76
-
77
- >>> filename = ' /Users/guido/programs/spam.py'
78
- >>> import os.path
79
- >>> os.path.basename(filename)
80
- 'spam.py'
81
- >>> os.path.dirname(filename)
82
- '/Users/guido/programs'
83
- >>> os.path.split(filename)
84
- ('/Users/guido/programs', 'spam.py')
85
- >>> os.path.join(' /new/dir' , os.path.basename(filename))
86
- '/new/dir/spam.py'
87
- >>> os.path.expanduser(' ~/guido/programs/spam.py' )
88
- '/Users/guido/programs/spam.py'
89
- >>>
90
-
91
- One tricky bit about copying directories with copytree() is the handling of errors. For
92
- example, in the process of copying, the function might encounter broken symbolic links,
93
- files that can’t be accessed due to permission problems, and so on. To deal with this, all
94
- exceptions encountered are collected into a list and grouped into a single exception that
95
- gets raised at the end of the operation. Here is how you would handle it:
96
-
97
- try:
98
- shutil.copytree(src, dst)
99
- except shutil.Error as e:
100
- for src, dst, msg in e.args[0]:
101
- # src is source name
102
- # dst is destination name
103
- # msg is error message from exception
104
- print(dst, src, msg)
105
-
106
- If you supply the ignore_dangling_symlinks=True keyword argument, then copy
107
- tree() will ignore dangling symlinks.
108
- The functions shown in this recipe are probably the most commonly used. However,
109
- shutil has many more operations related to copying data. The documentation is def‐
110
- initely worth a further look. See the Python documentation.
69
+ 使用 ``shutil `` 复制文件和目录也忒简单了点吧。
70
+ 不过,对于文件元数据信息,``copy2() `` 这样的函数只能尽自己最大能力来保留它。
71
+ 访问时间、创建时间和权限这些基本信息会被保留,
72
+ 但是对于所有者、ACLs、资源fork和其他更深层次的文件元信息就说不准了,
73
+ 这个还得依赖于底层操作系统类型和用户所拥有的访问权限。
74
+ 你通常不会去使用 ``shutil.copytree() `` 函数来执行系统备份。
75
+ 当处理文件名的时候,最好使用 ``os.path `` 中的函数来确保最大的可移植性(特别是同时要适用于Unix和Windows)。
76
+ 例如:
77
+
78
+ .. code-block :: python
79
+
80
+ >> > filename = ' /Users/guido/programs/spam.py'
81
+ >> > import os.path
82
+ >> > os.path.basename(filename)
83
+ ' spam.py'
84
+ >> > os.path.dirname(filename)
85
+ ' /Users/guido/programs'
86
+ >> > os.path.split(filename)
87
+ (' /Users/guido/programs' , ' spam.py' )
88
+ >> > os.path.join(' /new/dir' , os.path.basename(filename))
89
+ ' /new/dir/spam.py'
90
+ >> > os.path.expanduser(' ~/guido/programs/spam.py' )
91
+ ' /Users/guido/programs/spam.py'
92
+ >> >
93
+
94
+ 使用 ``copytree() `` 复制文件夹的一个棘手的问题是对于错误的处理。
95
+ 例如,在复制过程中,函数可能会碰到损坏的符号链接,因为权限无法访问文件的问题等等。
96
+ 为了解决这个问题,所有碰到的问题会被收集到一个列表中并打包为一个单独的异常,到了最后再抛出。
97
+ 下面是一个例子:
98
+
99
+ .. code-block :: python
100
+
101
+ try :
102
+ shutil.copytree(src, dst)
103
+ except shutil.Error as e:
104
+ for src, dst, msg in e.args[0 ]:
105
+ # src is source name
106
+ # dst is destination name
107
+ # msg is error message from exception
108
+ print (dst, src, msg)
109
+
110
+ 如果你提供关键字参数 ``ignore_dangling_symlinks=True `` ,
111
+ 这时候 ``copytree() `` 会忽略掉无效符号链接。
112
+
113
+ 本节演示的这些函数都是最常见的。不过,``shutil `` 还有更多的和复制数据相关的操作。
114
+ 它的文档很值得一看,参考 `Python documentation <https://docs.python.org/3/library/shutil.html >`_
0 commit comments