blob: 6d1857033c2241cbe705c61d8f2dee2153c43046 [file] [log] [blame]
Guido van Rossum9d0a3df1997-04-29 14:45:19 +00001"""Utility functions for copying files.
2
3XXX The functions here don't copy the data fork or other metadata on Mac.
4
5"""
Guido van Rossumc6360141990-10-13 19:23:40 +00006
Guido van Rossumc96207a1992-03-31 18:55:40 +00007import os
Guido van Rossum9d0a3df1997-04-29 14:45:19 +00008import stat
Guido van Rossumc6360141990-10-13 19:23:40 +00009
Guido van Rossumc6360141990-10-13 19:23:40 +000010
Guido van Rossumc6360141990-10-13 19:23:40 +000011def copyfile(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000012 """Copy data from src to dst"""
Guido van Rossuma2baf461997-04-29 14:06:46 +000013 fsrc = None
14 fdst = None
15 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000016 fsrc = open(src, 'rb')
17 fdst = open(dst, 'wb')
18 while 1:
19 buf = fsrc.read(16*1024)
20 if not buf:
21 break
22 fdst.write(buf)
Guido van Rossuma2baf461997-04-29 14:06:46 +000023 finally:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000024 if fdst:
25 fdst.close()
26 if fsrc:
27 fsrc.close()
Guido van Rossumc6360141990-10-13 19:23:40 +000028
Guido van Rossumc6360141990-10-13 19:23:40 +000029def copymode(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000030 """Copy mode bits from src to dst"""
Guido van Rossuma2baf461997-04-29 14:06:46 +000031 st = os.stat(src)
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000032 mode = stat.S_IMODE(st[stat.ST_MODE])
Guido van Rossuma2baf461997-04-29 14:06:46 +000033 os.chmod(dst, mode)
Guido van Rossumc6360141990-10-13 19:23:40 +000034
Guido van Rossumc6360141990-10-13 19:23:40 +000035def copystat(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000036 """Copy all stat info (mode bits, atime and mtime) from src to dst"""
Guido van Rossuma2baf461997-04-29 14:06:46 +000037 st = os.stat(src)
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000038 mode = stat.S_IMODE(st[stat.ST_MODE])
Guido van Rossuma2baf461997-04-29 14:06:46 +000039 os.chmod(dst, mode)
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000040 os.utime(dst, (st[stat.ST_ATIME], st[stat.ST_MODE]))
Guido van Rossumc6360141990-10-13 19:23:40 +000041
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000042
Guido van Rossumc6360141990-10-13 19:23:40 +000043def copy(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000044 """Copy data and mode bits ("cp src dst").
45
46 The destination may be a directory.
47
48 """
Guido van Rossuma2baf461997-04-29 14:06:46 +000049 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000050 dst = os.path.join(dst, os.path.basename(src))
Guido van Rossuma2baf461997-04-29 14:06:46 +000051 copyfile(src, dst)
52 copymode(src, dst)
Guido van Rossumc6360141990-10-13 19:23:40 +000053
Guido van Rossumc6360141990-10-13 19:23:40 +000054def copy2(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000055 """Copy data and all stat info ("cp -p src dst").
56
57 The destination may be a directory.
58
59 """
Guido van Rossuma2baf461997-04-29 14:06:46 +000060 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000061 dst = os.path.join(dst, os.path.basename(src))
Guido van Rossuma2baf461997-04-29 14:06:46 +000062 copyfile(src, dst)
63 copystat(src, dst)
Guido van Rossumc6360141990-10-13 19:23:40 +000064
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000065
66def copytree(src, dst, symlinks=0):
67 """Recursively copy a directory tree using copy2().
68
69 The destination directory must not already exist.
70 Error are reported to standard output.
71
72 If the optional symlinks flag is true, symbolic links in the
73 source tree result in symbolic links in the destination tree; if
74 it is false, the contents of the files pointed to by symbolic
75 links are copied.
76
77 XXX Consider this example code rather than the ultimate tool.
78
79 """
Guido van Rossuma2baf461997-04-29 14:06:46 +000080 names = os.listdir(src)
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000081 os.mkdir(dst)
Guido van Rossuma2baf461997-04-29 14:06:46 +000082 for name in names:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000083 srcname = os.path.join(src, name)
84 dstname = os.path.join(dst, name)
85 try:
86 if symlinks and os.path.islink(srcname):
87 linkto = os.readlink(srcname)
88 os.symlink(linkto, dstname)
89 elif os.path.isdir(srcname):
90 copytree(srcname, dstname)
91 else:
92 copy2(srcname, dstname)
93 # XXX What about devices, sockets etc.?
94 except (IOError, os.error), why:
95 print "Can't copy %s to %s: %s" % (`srcname`, `dstname`, str(why))
Guido van Rossumd7673291998-02-06 21:38:09 +000096
97def rmtree(path, ignore_errors=0, onerror=None):
98 """Recursively delete a directory tree.
99
100 If ignore_errors is set, errors are ignored; otherwise, if
101 onerror is set, it is called to handle the error; otherwise, an
102 exception is raised.
103
104 """
105 cmdtuples = []
106 _build_cmdtuple(path, cmdtuples)
107 for cmd in cmdtuples:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000108 try:
109 apply(cmd[0], (cmd[1],))
110 except:
111 exc = sys.exc_info()
112 if ignore_errors:
113 pass
114 elif onerror:
115 onerror(cmd[0], cmd[1], exc)
116 else:
117 raise exc[0], (exc[1][0], exc[1][1] + ' removing '+cmd[1])
Guido van Rossumd7673291998-02-06 21:38:09 +0000118
119# Helper for rmtree()
120def _build_cmdtuple(path, cmdtuples):
121 for f in os.listdir(path):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000122 real_f = os.path.join(path,f)
123 if os.path.isdir(real_f) and not os.path.islink(real_f):
124 _build_cmdtuple(real_f, cmdtuples)
125 else:
126 cmdtuples.append(os.remove, real_f)
Guido van Rossumd7673291998-02-06 21:38:09 +0000127 cmdtuples.append(os.rmdir, path)