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