blob: c3ff687bff4efcd407f16cddbf71995f7d8962b2 [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
Brett Cannon1c3fa182004-06-19 21:11:35 +000010from os.path import abspath
Guido van Rossumc6360141990-10-13 19:23:40 +000011
Skip Montanaro0de65802001-02-15 22:15:14 +000012__all__ = ["copyfileobj","copyfile","copymode","copystat","copy","copy2",
Raymond Hettinger2b9bfb32002-10-30 05:44:50 +000013 "copytree","move","rmtree","Error"]
Martin v. Löwise9ce0b02002-10-07 13:23:24 +000014
Neal Norwitz4ce69a52005-09-01 00:45:28 +000015class Error(EnvironmentError):
Martin v. Löwise9ce0b02002-10-07 13:23:24 +000016 pass
Guido van Rossumc6360141990-10-13 19:23:40 +000017
Greg Stein42bb8b32000-07-12 09:55:30 +000018def copyfileobj(fsrc, fdst, length=16*1024):
19 """copy data from file-like object fsrc to file-like object fdst"""
20 while 1:
21 buf = fsrc.read(length)
22 if not buf:
23 break
24 fdst.write(buf)
25
Johannes Gijsbers46f14592004-08-14 13:30:02 +000026def _samefile(src, dst):
27 # Macintosh, Unix.
28 if hasattr(os.path,'samefile'):
Johannes Gijsbersf9a098e2004-08-14 14:51:01 +000029 try:
30 return os.path.samefile(src, dst)
31 except OSError:
32 return False
Johannes Gijsbers46f14592004-08-14 13:30:02 +000033
34 # All other platforms: check for same pathname.
35 return (os.path.normcase(os.path.abspath(src)) ==
36 os.path.normcase(os.path.abspath(dst)))
Tim Peters495ad3c2001-01-15 01:36:40 +000037
Guido van Rossumc6360141990-10-13 19:23:40 +000038def copyfile(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000039 """Copy data from src to dst"""
Johannes Gijsbers46f14592004-08-14 13:30:02 +000040 if _samefile(src, dst):
41 raise Error, "`%s` and `%s` are the same file" % (src, dst)
42
Guido van Rossuma2baf461997-04-29 14:06:46 +000043 fsrc = None
44 fdst = None
45 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000046 fsrc = open(src, 'rb')
47 fdst = open(dst, 'wb')
Greg Stein42bb8b32000-07-12 09:55:30 +000048 copyfileobj(fsrc, fdst)
Guido van Rossuma2baf461997-04-29 14:06:46 +000049 finally:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000050 if fdst:
51 fdst.close()
52 if fsrc:
53 fsrc.close()
Guido van Rossumc6360141990-10-13 19:23:40 +000054
Guido van Rossumc6360141990-10-13 19:23:40 +000055def copymode(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000056 """Copy mode bits from src to dst"""
Tim Peters0c947242001-01-21 20:00:00 +000057 if hasattr(os, 'chmod'):
58 st = os.stat(src)
Walter Dörwald294bbf32002-06-06 09:48:13 +000059 mode = stat.S_IMODE(st.st_mode)
Tim Peters0c947242001-01-21 20:00:00 +000060 os.chmod(dst, mode)
Guido van Rossumc6360141990-10-13 19:23:40 +000061
Guido van Rossumc6360141990-10-13 19:23:40 +000062def copystat(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000063 """Copy all stat info (mode bits, atime and mtime) from src to dst"""
Guido van Rossuma2baf461997-04-29 14:06:46 +000064 st = os.stat(src)
Walter Dörwald294bbf32002-06-06 09:48:13 +000065 mode = stat.S_IMODE(st.st_mode)
Tim Peters0c947242001-01-21 20:00:00 +000066 if hasattr(os, 'utime'):
Walter Dörwald294bbf32002-06-06 09:48:13 +000067 os.utime(dst, (st.st_atime, st.st_mtime))
Tim Peters0c947242001-01-21 20:00:00 +000068 if hasattr(os, 'chmod'):
69 os.chmod(dst, mode)
Guido van Rossumc6360141990-10-13 19:23:40 +000070
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000071
Guido van Rossumc6360141990-10-13 19:23:40 +000072def copy(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000073 """Copy data and mode bits ("cp src dst").
Tim Peters495ad3c2001-01-15 01:36:40 +000074
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000075 The destination may be a directory.
76
77 """
Guido van Rossuma2baf461997-04-29 14:06:46 +000078 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000079 dst = os.path.join(dst, os.path.basename(src))
Guido van Rossuma2baf461997-04-29 14:06:46 +000080 copyfile(src, dst)
81 copymode(src, dst)
Guido van Rossumc6360141990-10-13 19:23:40 +000082
Guido van Rossumc6360141990-10-13 19:23:40 +000083def copy2(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000084 """Copy data and all stat info ("cp -p src dst").
85
86 The destination may be a directory.
87
88 """
Guido van Rossuma2baf461997-04-29 14:06:46 +000089 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000090 dst = os.path.join(dst, os.path.basename(src))
Guido van Rossuma2baf461997-04-29 14:06:46 +000091 copyfile(src, dst)
92 copystat(src, dst)
Guido van Rossumc6360141990-10-13 19:23:40 +000093
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000094
Neal Norwitza4c93b62003-02-23 21:36:32 +000095def copytree(src, dst, symlinks=False):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000096 """Recursively copy a directory tree using copy2().
97
98 The destination directory must not already exist.
Neal Norwitza4c93b62003-02-23 21:36:32 +000099 If exception(s) occur, an Error is raised with a list of reasons.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000100
101 If the optional symlinks flag is true, symbolic links in the
102 source tree result in symbolic links in the destination tree; if
103 it is false, the contents of the files pointed to by symbolic
104 links are copied.
105
106 XXX Consider this example code rather than the ultimate tool.
107
108 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000109 names = os.listdir(src)
Johannes Gijsberse4172ea2005-01-08 12:31:29 +0000110 os.makedirs(dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000111 errors = []
Guido van Rossuma2baf461997-04-29 14:06:46 +0000112 for name in names:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000113 srcname = os.path.join(src, name)
114 dstname = os.path.join(dst, name)
115 try:
116 if symlinks and os.path.islink(srcname):
117 linkto = os.readlink(srcname)
118 os.symlink(linkto, dstname)
119 elif os.path.isdir(srcname):
Fred Drake5fa38862000-04-07 14:34:50 +0000120 copytree(srcname, dstname, symlinks)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000121 else:
122 copy2(srcname, dstname)
123 # XXX What about devices, sockets etc.?
124 except (IOError, os.error), why:
Georg Brandl7a3fd892006-04-28 16:54:25 +0000125 errors.append((srcname, dstname, str(why)))
Georg Brandla1be88e2005-08-31 22:48:45 +0000126 # catch the Error from the recursive copytree so that we can
127 # continue with other files
128 except Error, err:
129 errors.extend(err.args[0])
Martin v. Löwis4e678382006-07-30 13:00:31 +0000130 try:
131 copystat(src, dst)
132 except WindowsError:
133 # can't copy file access times on Windows
134 pass
135 except OSError, why:
136 errors.extend((src, dst, str(why)))
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000137 if errors:
138 raise Error, errors
Guido van Rossumd7673291998-02-06 21:38:09 +0000139
Barry Warsaw234d9a92003-01-24 17:36:15 +0000140def rmtree(path, ignore_errors=False, onerror=None):
Guido van Rossumd7673291998-02-06 21:38:09 +0000141 """Recursively delete a directory tree.
142
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000143 If ignore_errors is set, errors are ignored; otherwise, if onerror
144 is set, it is called to handle the error with arguments (func,
145 path, exc_info) where func is os.listdir, os.remove, or os.rmdir;
146 path is the argument to that function that caused it to fail; and
147 exc_info is a tuple returned by sys.exc_info(). If ignore_errors
148 is false and onerror is None, an exception is raised.
149
Guido van Rossumd7673291998-02-06 21:38:09 +0000150 """
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000151 if ignore_errors:
152 def onerror(*args):
Barry Warsaw234d9a92003-01-24 17:36:15 +0000153 pass
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000154 elif onerror is None:
155 def onerror(*args):
156 raise
157 names = []
158 try:
159 names = os.listdir(path)
160 except os.error, err:
161 onerror(os.listdir, path, sys.exc_info())
162 for name in names:
163 fullname = os.path.join(path, name)
164 try:
165 mode = os.lstat(fullname).st_mode
166 except os.error:
167 mode = 0
168 if stat.S_ISDIR(mode):
169 rmtree(fullname, ignore_errors, onerror)
Barry Warsaw234d9a92003-01-24 17:36:15 +0000170 else:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000171 try:
172 os.remove(fullname)
173 except os.error, err:
174 onerror(os.remove, fullname, sys.exc_info())
175 try:
176 os.rmdir(path)
177 except os.error:
178 onerror(os.rmdir, path, sys.exc_info())
Guido van Rossumd7673291998-02-06 21:38:09 +0000179
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000180def move(src, dst):
181 """Recursively move a file or directory to another location.
182
183 If the destination is on our current filesystem, then simply use
184 rename. Otherwise, copy src to the dst and then remove src.
185 A lot more could be done here... A look at a mv.c shows a lot of
186 the issues this implementation glosses over.
187
188 """
189
190 try:
191 os.rename(src, dst)
192 except OSError:
193 if os.path.isdir(src):
Brett Cannon1c3fa182004-06-19 21:11:35 +0000194 if destinsrc(src, dst):
195 raise Error, "Cannot move a directory '%s' into itself '%s'." % (src, dst)
Neal Norwitza4c93b62003-02-23 21:36:32 +0000196 copytree(src, dst, symlinks=True)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000197 rmtree(src)
198 else:
199 copy2(src,dst)
200 os.unlink(src)
Brett Cannon1c3fa182004-06-19 21:11:35 +0000201
202def destinsrc(src, dst):
203 return abspath(dst).startswith(abspath(src))