blob: 0e60870957cc6f1bce8c4abaa644cbdae5d6bc99 [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
Skip Montanaro0de65802001-02-15 22:15:14 +000011__all__ = ["copyfileobj","copyfile","copymode","copystat","copy","copy2",
12 "copytree","rmtree"]
Guido van Rossumc6360141990-10-13 19:23:40 +000013
Greg Stein42bb8b32000-07-12 09:55:30 +000014def copyfileobj(fsrc, fdst, length=16*1024):
15 """copy data from file-like object fsrc to file-like object fdst"""
16 while 1:
17 buf = fsrc.read(length)
18 if not buf:
19 break
20 fdst.write(buf)
21
Tim Peters495ad3c2001-01-15 01:36:40 +000022
Guido van Rossumc6360141990-10-13 19:23:40 +000023def copyfile(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000024 """Copy data from src to dst"""
Guido van Rossuma2baf461997-04-29 14:06:46 +000025 fsrc = None
26 fdst = None
Raymond Hettinger57e79452002-09-08 20:43:59 +000027 # check for same pathname; all platforms
28 _src = os.path.normcase(os.path.abspath(src))
29 _dst = os.path.normcase(os.path.abspath(dst))
30 if _src == _dst:
31 return
Guido van Rossuma2baf461997-04-29 14:06:46 +000032 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000033 fsrc = open(src, 'rb')
34 fdst = open(dst, 'wb')
Greg Stein42bb8b32000-07-12 09:55:30 +000035 copyfileobj(fsrc, fdst)
Guido van Rossuma2baf461997-04-29 14:06:46 +000036 finally:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000037 if fdst:
38 fdst.close()
39 if fsrc:
40 fsrc.close()
Guido van Rossumc6360141990-10-13 19:23:40 +000041
Guido van Rossumc6360141990-10-13 19:23:40 +000042def copymode(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000043 """Copy mode bits from src to dst"""
Tim Peters0c947242001-01-21 20:00:00 +000044 if hasattr(os, 'chmod'):
45 st = os.stat(src)
Walter Dörwald294bbf32002-06-06 09:48:13 +000046 mode = stat.S_IMODE(st.st_mode)
Tim Peters0c947242001-01-21 20:00:00 +000047 os.chmod(dst, mode)
Guido van Rossumc6360141990-10-13 19:23:40 +000048
Guido van Rossumc6360141990-10-13 19:23:40 +000049def copystat(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000050 """Copy all stat info (mode bits, atime and mtime) from src to dst"""
Guido van Rossuma2baf461997-04-29 14:06:46 +000051 st = os.stat(src)
Walter Dörwald294bbf32002-06-06 09:48:13 +000052 mode = stat.S_IMODE(st.st_mode)
Tim Peters0c947242001-01-21 20:00:00 +000053 if hasattr(os, 'utime'):
Walter Dörwald294bbf32002-06-06 09:48:13 +000054 os.utime(dst, (st.st_atime, st.st_mtime))
Tim Peters0c947242001-01-21 20:00:00 +000055 if hasattr(os, 'chmod'):
56 os.chmod(dst, mode)
Guido van Rossumc6360141990-10-13 19:23:40 +000057
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000058
Guido van Rossumc6360141990-10-13 19:23:40 +000059def copy(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000060 """Copy data and mode bits ("cp src dst").
Tim Peters495ad3c2001-01-15 01:36:40 +000061
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000062 The destination may be a directory.
63
64 """
Guido van Rossuma2baf461997-04-29 14:06:46 +000065 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000066 dst = os.path.join(dst, os.path.basename(src))
Guido van Rossuma2baf461997-04-29 14:06:46 +000067 copyfile(src, dst)
68 copymode(src, dst)
Guido van Rossumc6360141990-10-13 19:23:40 +000069
Guido van Rossumc6360141990-10-13 19:23:40 +000070def copy2(src, dst):
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000071 """Copy data and all stat info ("cp -p src dst").
72
73 The destination may be a directory.
74
75 """
Guido van Rossuma2baf461997-04-29 14:06:46 +000076 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000077 dst = os.path.join(dst, os.path.basename(src))
Guido van Rossuma2baf461997-04-29 14:06:46 +000078 copyfile(src, dst)
79 copystat(src, dst)
Guido van Rossumc6360141990-10-13 19:23:40 +000080
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000081
82def copytree(src, dst, symlinks=0):
83 """Recursively copy a directory tree using copy2().
84
85 The destination directory must not already exist.
86 Error are reported to standard output.
87
88 If the optional symlinks flag is true, symbolic links in the
89 source tree result in symbolic links in the destination tree; if
90 it is false, the contents of the files pointed to by symbolic
91 links are copied.
92
93 XXX Consider this example code rather than the ultimate tool.
94
95 """
Guido van Rossuma2baf461997-04-29 14:06:46 +000096 names = os.listdir(src)
Guido van Rossum9d0a3df1997-04-29 14:45:19 +000097 os.mkdir(dst)
Guido van Rossuma2baf461997-04-29 14:06:46 +000098 for name in names:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000099 srcname = os.path.join(src, name)
100 dstname = os.path.join(dst, name)
101 try:
102 if symlinks and os.path.islink(srcname):
103 linkto = os.readlink(srcname)
104 os.symlink(linkto, dstname)
105 elif os.path.isdir(srcname):
Fred Drake5fa38862000-04-07 14:34:50 +0000106 copytree(srcname, dstname, symlinks)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000107 else:
108 copy2(srcname, dstname)
109 # XXX What about devices, sockets etc.?
110 except (IOError, os.error), why:
111 print "Can't copy %s to %s: %s" % (`srcname`, `dstname`, str(why))
Guido van Rossumd7673291998-02-06 21:38:09 +0000112
113def rmtree(path, ignore_errors=0, onerror=None):
114 """Recursively delete a directory tree.
115
116 If ignore_errors is set, errors are ignored; otherwise, if
117 onerror is set, it is called to handle the error; otherwise, an
118 exception is raised.
119
120 """
121 cmdtuples = []
122 _build_cmdtuple(path, cmdtuples)
123 for cmd in cmdtuples:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000124 try:
125 apply(cmd[0], (cmd[1],))
126 except:
127 exc = sys.exc_info()
128 if ignore_errors:
129 pass
Raymond Hettingerf13eb552002-06-02 00:40:05 +0000130 elif onerror is not None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000131 onerror(cmd[0], cmd[1], exc)
132 else:
133 raise exc[0], (exc[1][0], exc[1][1] + ' removing '+cmd[1])
Guido van Rossumd7673291998-02-06 21:38:09 +0000134
135# Helper for rmtree()
136def _build_cmdtuple(path, cmdtuples):
137 for f in os.listdir(path):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000138 real_f = os.path.join(path,f)
139 if os.path.isdir(real_f) and not os.path.islink(real_f):
140 _build_cmdtuple(real_f, cmdtuples)
141 else:
Guido van Rossumd832f9e1998-10-07 13:18:17 +0000142 cmdtuples.append((os.remove, real_f))
143 cmdtuples.append((os.rmdir, path))