blob: b05436ed800a96dbe67e95d60d65fc6c87643ecf [file] [log] [blame]
Guido van Rossum15e22e11997-12-05 19:03:01 +00001# Module 'ntpath' -- common operations on WinNT/Win95 pathnames
Tim Peters2344fae2001-01-15 00:50:52 +00002"""Common pathname manipulations, WindowsNT/95 version.
Guido van Rossum534972b1999-02-03 17:20:50 +00003
4Instead of importing this module directly, import os and refer to this
5module as os.path.
Guido van Rossum15e22e11997-12-05 19:03:01 +00006"""
Guido van Rossum555915a1994-02-24 11:32:59 +00007
8import os
Mark Hammond8696ebc2002-10-08 02:44:31 +00009import sys
Christian Heimes05e8be12008-02-23 18:30:17 +000010import stat
Guido van Rossumd8faa362007-04-27 19:54:29 +000011import genericpath
Thomas Wouters89f507f2006-12-13 04:49:30 +000012from genericpath import *
Skip Montanaro4d5d5bf2000-07-13 01:01:03 +000013
Skip Montanaro269b83b2001-02-06 01:07:02 +000014__all__ = ["normcase","isabs","join","splitdrive","split","splitext",
15 "basename","dirname","commonprefix","getsize","getmtime",
Georg Brandlf0de6a12005-08-22 18:02:59 +000016 "getatime","getctime", "islink","exists","lexists","isdir","isfile",
Benjamin Petersond71ca412008-05-08 23:44:58 +000017 "ismount", "expanduser","expandvars","normpath","abspath",
Georg Brandlf0de6a12005-08-22 18:02:59 +000018 "splitunc","curdir","pardir","sep","pathsep","defpath","altsep",
Brian Curtind40e6f72010-07-08 21:39:08 +000019 "extsep","devnull","realpath","supports_unicode_filenames","relpath",
Brian Curtin62857742010-09-06 17:07:27 +000020 "samefile", "sameopenfile",]
Guido van Rossum555915a1994-02-24 11:32:59 +000021
Skip Montanaro117910d2003-02-14 19:35:31 +000022# strings representing various path-related bits and pieces
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +000023# These are primarily for export; internally, they are hardcoded.
Skip Montanaro117910d2003-02-14 19:35:31 +000024curdir = '.'
25pardir = '..'
26extsep = '.'
27sep = '\\'
28pathsep = ';'
Skip Montanaro9ddac3e2003-03-28 22:23:24 +000029altsep = '/'
Andrew MacIntyre437966c2003-02-17 09:17:50 +000030defpath = '.;C:\\bin'
Skip Montanaro117910d2003-02-14 19:35:31 +000031if 'ce' in sys.builtin_module_names:
32 defpath = '\\Windows'
33elif 'os2' in sys.builtin_module_names:
Andrew MacIntyre437966c2003-02-17 09:17:50 +000034 # OS/2 w/ VACPP
Skip Montanaro117910d2003-02-14 19:35:31 +000035 altsep = '/'
Martin v. Löwisbdec50f2004-06-08 08:29:33 +000036devnull = 'nul'
Skip Montanaro117910d2003-02-14 19:35:31 +000037
Mark Hammond5a607a32009-05-06 08:04:54 +000038def _get_empty(path):
39 if isinstance(path, bytes):
40 return b''
41 else:
42 return ''
43
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +000044def _get_sep(path):
45 if isinstance(path, bytes):
46 return b'\\'
47 else:
48 return '\\'
49
50def _get_altsep(path):
51 if isinstance(path, bytes):
52 return b'/'
53 else:
54 return '/'
55
56def _get_bothseps(path):
57 if isinstance(path, bytes):
58 return b'\\/'
59 else:
60 return '\\/'
61
62def _get_dot(path):
63 if isinstance(path, bytes):
64 return b'.'
65 else:
66 return '.'
67
68def _get_colon(path):
69 if isinstance(path, bytes):
70 return b':'
71 else:
72 return ':'
73
Georg Brandlcfb68212010-07-31 21:40:15 +000074def _get_special(path):
75 if isinstance(path, bytes):
76 return (b'\\\\.\\', b'\\\\?\\')
77 else:
78 return ('\\\\.\\', '\\\\?\\')
79
Guido van Rossume2ad88c1997-08-12 14:46:58 +000080# Normalize the case of a pathname and map slashes to backslashes.
81# Other normalizations (such as optimizing '../' away) are not done
Guido van Rossum555915a1994-02-24 11:32:59 +000082# (this is done by normpath).
Guido van Rossume2ad88c1997-08-12 14:46:58 +000083
Guido van Rossum555915a1994-02-24 11:32:59 +000084def normcase(s):
Guido van Rossum16a0bc21998-02-18 13:48:31 +000085 """Normalize case of pathname.
86
Guido van Rossum534972b1999-02-03 17:20:50 +000087 Makes all characters lowercase and all slashes into backslashes."""
Ezio Melotti5a3ef5b2010-06-25 10:56:11 +000088 if not isinstance(s, (bytes, str)):
89 raise TypeError("normcase() argument must be str or bytes, "
90 "not '{}'".format(s.__class__.__name__))
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +000091 return s.replace(_get_altsep(s), _get_sep(s)).lower()
Guido van Rossum555915a1994-02-24 11:32:59 +000092
Guido van Rossum77e1db31997-06-02 23:11:57 +000093
Fred Drakeef0b5dd2000-02-17 17:30:40 +000094# Return whether a path is absolute.
Mark Hammond5a607a32009-05-06 08:04:54 +000095# Trivial in Posix, harder on Windows.
96# For Windows it is absolute if it starts with a slash or backslash (current
97# volume), or if a pathname after the volume-letter-and-colon or UNC-resource
Guido van Rossum534972b1999-02-03 17:20:50 +000098# starts with a slash or backslash.
Guido van Rossum555915a1994-02-24 11:32:59 +000099
100def isabs(s):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000101 """Test whether a path is absolute"""
102 s = splitdrive(s)[1]
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000103 return len(s) > 0 and s[:1] in _get_bothseps(s)
Guido van Rossum555915a1994-02-24 11:32:59 +0000104
105
Guido van Rossum77e1db31997-06-02 23:11:57 +0000106# Join two (or more) paths.
107
Barry Warsaw384d2491997-02-18 21:53:25 +0000108def join(a, *p):
Guido van Rossum04110fb2007-08-24 16:32:05 +0000109 """Join two or more pathname components, inserting "\\" as needed.
110 If any component is an absolute path, all previous path components
111 will be discarded."""
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000112 sep = _get_sep(a)
113 seps = _get_bothseps(a)
114 colon = _get_colon(a)
Guido van Rossum15e22e11997-12-05 19:03:01 +0000115 path = a
116 for b in p:
Tim Peters33dc0a12001-07-27 08:09:54 +0000117 b_wins = 0 # set to 1 iff b makes path irrelevant
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000118 if not path:
Tim Peters33dc0a12001-07-27 08:09:54 +0000119 b_wins = 1
Tim Peters1bdd0f22001-07-19 17:18:18 +0000120
Tim Peters33dc0a12001-07-27 08:09:54 +0000121 elif isabs(b):
122 # This probably wipes out path so far. However, it's more
Mark Hammond5a607a32009-05-06 08:04:54 +0000123 # complicated if path begins with a drive letter. You get a+b
124 # (minus redundant slashes) in these four cases:
Tim Peters33dc0a12001-07-27 08:09:54 +0000125 # 1. join('c:', '/a') == 'c:/a'
Mark Hammond5a607a32009-05-06 08:04:54 +0000126 # 2. join('//computer/share', '/a') == '//computer/share/a'
127 # 3. join('c:/', '/a') == 'c:/a'
128 # 4. join('//computer/share/', '/a') == '//computer/share/a'
129 # But b wins in all of these cases:
130 # 5. join('c:/a', '/b') == '/b'
131 # 6. join('//computer/share/a', '/b') == '/b'
132 # 7. join('c:', 'd:/') == 'd:/'
133 # 8. join('c:', '//computer/share/') == '//computer/share/'
134 # 9. join('//computer/share', 'd:/') == 'd:/'
135 # 10. join('//computer/share', '//computer/share/') == '//computer/share/'
136 # 11. join('c:/', 'd:/') == 'd:/'
137 # 12. join('c:/', '//computer/share/') == '//computer/share/'
138 # 13. join('//computer/share/', 'd:/') == 'd:/'
139 # 14. join('//computer/share/', '//computer/share/') == '//computer/share/'
140 b_prefix, b_rest = splitdrive(b)
Tim Peters1bdd0f22001-07-19 17:18:18 +0000141
Mark Hammond5a607a32009-05-06 08:04:54 +0000142 # if b has a prefix, it always wins.
143 if b_prefix:
Tim Peters33dc0a12001-07-27 08:09:54 +0000144 b_wins = 1
Mark Hammond5a607a32009-05-06 08:04:54 +0000145 else:
146 # b doesn't have a prefix.
147 # but isabs(b) returned true.
148 # and therefore b_rest[0] must be a slash.
149 # (but let's check that.)
150 assert(b_rest and b_rest[0] in seps)
151
152 # so, b still wins if path has a rest that's more than a sep.
153 # you get a+b if path_rest is empty or only has a sep.
154 # (see cases 1-4 for times when b loses.)
155 path_rest = splitdrive(path)[1]
156 b_wins = path_rest and path_rest not in seps
Tim Peters1bdd0f22001-07-19 17:18:18 +0000157
Tim Peters33dc0a12001-07-27 08:09:54 +0000158 if b_wins:
159 path = b
160 else:
161 # Join, and ensure there's a separator.
162 assert len(path) > 0
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000163 if path[-1:] in seps:
164 if b and b[:1] in seps:
Tim Peters33dc0a12001-07-27 08:09:54 +0000165 path += b[1:]
166 else:
167 path += b
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000168 elif path[-1:] == colon:
Tim Peters33dc0a12001-07-27 08:09:54 +0000169 path += b
170 elif b:
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000171 if b[:1] in seps:
Tim Peters33dc0a12001-07-27 08:09:54 +0000172 path += b
173 else:
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000174 path += sep + b
Tim Peters6a3e5f12001-11-05 21:25:02 +0000175 else:
176 # path is not empty and does not end with a backslash,
177 # but b is empty; since, e.g., split('a/') produces
178 # ('a', ''), it's best if join() adds a backslash in
179 # this case.
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000180 path += sep
Tim Peters1bdd0f22001-07-19 17:18:18 +0000181
Guido van Rossum15e22e11997-12-05 19:03:01 +0000182 return path
Guido van Rossum555915a1994-02-24 11:32:59 +0000183
184
185# Split a path in a drive specification (a drive letter followed by a
Guido van Rossumf3c695c1999-04-06 19:32:19 +0000186# colon) and the path specification.
Guido van Rossum555915a1994-02-24 11:32:59 +0000187# It is always true that drivespec + pathspec == p
188def splitdrive(p):
Mark Hammond5a607a32009-05-06 08:04:54 +0000189 """Split a pathname into drive/UNC sharepoint and relative path specifiers.
190 Returns a 2-tuple (drive_or_unc, path); either part may be empty.
191
192 If you assign
193 result = splitdrive(p)
194 It is always true that:
195 result[0] + result[1] == p
196
197 If the path contained a drive letter, drive_or_unc will contain everything
198 up to and including the colon. e.g. splitdrive("c:/dir") returns ("c:", "/dir")
199
200 If the path contained a UNC path, the drive_or_unc will contain the host name
201 and share up to but not including the fourth directory separator character.
202 e.g. splitdrive("//host/computer/dir") returns ("//host/computer", "/dir")
203
204 Paths cannot contain both a drive letter and a UNC path.
205
206 """
207 empty = _get_empty(p)
208 if len(p) > 1:
209 sep = _get_sep(p)
Serhiy Storchaka3d7e1152013-12-16 14:34:55 +0200210 normp = p.replace(_get_altsep(p), sep)
Mark Hammond5a607a32009-05-06 08:04:54 +0000211 if (normp[0:2] == sep*2) and (normp[2:3] != sep):
212 # is a UNC path:
213 # vvvvvvvvvvvvvvvvvvvv drive letter or UNC path
214 # \\machine\mountpoint\directory\etc\...
215 # directory ^^^^^^^^^^^^^^^
216 index = normp.find(sep, 2)
217 if index == -1:
218 return empty, p
219 index2 = normp.find(sep, index + 1)
220 # a UNC path can't have two slashes in a row
221 # (after the initial two)
222 if index2 == index + 1:
223 return empty, p
224 if index2 == -1:
225 index2 = len(p)
226 return p[:index2], p[index2:]
227 if normp[1:2] == _get_colon(p):
228 return p[:2], p[2:]
229 return empty, p
Guido van Rossumf3c695c1999-04-06 19:32:19 +0000230
231
232# Parse UNC paths
233def splitunc(p):
Mark Hammond5a607a32009-05-06 08:04:54 +0000234 """Deprecated since Python 3.1. Please use splitdrive() instead;
235 it now handles UNC paths.
236
237 Split a pathname into UNC mount point and relative path specifiers.
Guido van Rossumf3c695c1999-04-06 19:32:19 +0000238
239 Return a 2-tuple (unc, rest); either part may be empty.
240 If unc is not empty, it has the form '//host/mount' (or similar
241 using backslashes). unc+rest is always the input path.
242 Paths containing drive letters never have an UNC part.
243 """
Mark Hammond5a607a32009-05-06 08:04:54 +0000244 import warnings
245 warnings.warn("ntpath.splitunc is deprecated, use ntpath.splitdrive instead",
Serhiy Storchaka593568b2013-12-16 15:13:28 +0200246 DeprecationWarning, 2)
247 drive, path = splitdrive(p)
248 if len(drive) == 2:
249 # Drive letter present
250 return p[:0], p
251 return drive, path
Guido van Rossum555915a1994-02-24 11:32:59 +0000252
253
254# Split a path in head (everything up to the last '/') and tail (the
Guido van Rossum8f0fa9e1999-03-19 21:05:12 +0000255# rest). After the trailing '/' is stripped, the invariant
Guido van Rossum555915a1994-02-24 11:32:59 +0000256# join(head, tail) == p holds.
257# The resulting head won't end in '/' unless it is the root.
258
259def split(p):
Guido van Rossum534972b1999-02-03 17:20:50 +0000260 """Split a pathname.
261
262 Return tuple (head, tail) where tail is everything after the final slash.
263 Either part may be empty."""
Guido van Rossum8f0fa9e1999-03-19 21:05:12 +0000264
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000265 seps = _get_bothseps(p)
Guido van Rossum15e22e11997-12-05 19:03:01 +0000266 d, p = splitdrive(p)
Guido van Rossum8f0fa9e1999-03-19 21:05:12 +0000267 # set i to index beyond p's last slash
268 i = len(p)
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000269 while i and p[i-1] not in seps:
Georg Brandl599b65d2010-07-23 08:46:35 +0000270 i -= 1
Guido van Rossum8f0fa9e1999-03-19 21:05:12 +0000271 head, tail = p[:i], p[i:] # now tail has no slashes
272 # remove trailing slashes from head, unless it's all slashes
273 head2 = head
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000274 while head2 and head2[-1:] in seps:
Guido van Rossum8f0fa9e1999-03-19 21:05:12 +0000275 head2 = head2[:-1]
276 head = head2 or head
Guido van Rossum15e22e11997-12-05 19:03:01 +0000277 return d + head, tail
Guido van Rossum555915a1994-02-24 11:32:59 +0000278
279
280# Split a path in root and extension.
Guido van Rossum73e122f1997-01-22 00:17:26 +0000281# The extension is everything starting at the last dot in the last
Guido van Rossum555915a1994-02-24 11:32:59 +0000282# pathname component; the root is everything before that.
283# It is always true that root + ext == p.
284
285def splitext(p):
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000286 return genericpath._splitext(p, _get_sep(p), _get_altsep(p),
287 _get_dot(p))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000288splitext.__doc__ = genericpath._splitext.__doc__
Guido van Rossum555915a1994-02-24 11:32:59 +0000289
290
291# Return the tail (basename) part of a path.
292
293def basename(p):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000294 """Returns the final component of a pathname"""
295 return split(p)[1]
Guido van Rossum555915a1994-02-24 11:32:59 +0000296
297
298# Return the head (dirname) part of a path.
299
300def dirname(p):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000301 """Returns the directory component of a pathname"""
302 return split(p)[0]
Guido van Rossum555915a1994-02-24 11:32:59 +0000303
Guido van Rossum555915a1994-02-24 11:32:59 +0000304# Is a path a symbolic link?
Brian Curtind40e6f72010-07-08 21:39:08 +0000305# This will always return false on systems where os.lstat doesn't exist.
Guido van Rossum555915a1994-02-24 11:32:59 +0000306
307def islink(path):
Brian Curtind40e6f72010-07-08 21:39:08 +0000308 """Test whether a path is a symbolic link.
309 This will always return false for Windows prior to 6.0
310 and for OS/2.
Thomas Wouters89f507f2006-12-13 04:49:30 +0000311 """
Brian Curtind40e6f72010-07-08 21:39:08 +0000312 try:
313 st = os.lstat(path)
314 except (os.error, AttributeError):
315 return False
316 return stat.S_ISLNK(st.st_mode)
Guido van Rossum555915a1994-02-24 11:32:59 +0000317
Brian Curtind40e6f72010-07-08 21:39:08 +0000318# Being true for dangling symbolic links is also useful.
319
320def lexists(path):
321 """Test whether a path exists. Returns True for broken symbolic links"""
322 try:
323 st = os.lstat(path)
324 except (os.error, WindowsError):
325 return False
326 return True
Johannes Gijsbersae882f72004-08-30 10:19:56 +0000327
Guido van Rossumf3c695c1999-04-06 19:32:19 +0000328# Is a path a mount point? Either a root (with or without drive letter)
329# or an UNC path with at most a / or \ after the mount point.
Guido van Rossum555915a1994-02-24 11:32:59 +0000330
331def ismount(path):
Guido van Rossumca99c2c1998-01-19 22:25:59 +0000332 """Test whether a path is a mount point (defined as root of drive)"""
Benjamin Peterson48e24782009-03-29 13:02:52 +0000333 seps = _get_bothseps(path)
Mark Hammond5a607a32009-05-06 08:04:54 +0000334 root, rest = splitdrive(path)
335 if root and root[0] in seps:
336 return (not rest) or (rest in seps)
337 return rest in seps
Guido van Rossum555915a1994-02-24 11:32:59 +0000338
339
Guido van Rossum555915a1994-02-24 11:32:59 +0000340# Expand paths beginning with '~' or '~user'.
341# '~' means $HOME; '~user' means that user's home directory.
342# If the path doesn't begin with '~', or if the user or $HOME is unknown,
343# the path is returned unchanged (leaving error reporting to whatever
344# function is called with the expanded path as argument).
345# See also module 'glob' for expansion of *, ? and [...] in pathnames.
346# (A function should also be defined to do full *sh-style environment
347# variable expansion.)
348
349def expanduser(path):
Guido van Rossum534972b1999-02-03 17:20:50 +0000350 """Expand ~ and ~user constructs.
351
352 If user or $HOME is unknown, do nothing."""
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000353 if isinstance(path, bytes):
354 tilde = b'~'
355 else:
356 tilde = '~'
357 if not path.startswith(tilde):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000358 return path
359 i, n = 1, len(path)
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000360 while i < n and path[i] not in _get_bothseps(path):
Georg Brandl599b65d2010-07-23 08:46:35 +0000361 i += 1
Guido van Rossumd8faa362007-04-27 19:54:29 +0000362
363 if 'HOME' in os.environ:
364 userhome = os.environ['HOME']
365 elif 'USERPROFILE' in os.environ:
366 userhome = os.environ['USERPROFILE']
367 elif not 'HOMEPATH' in os.environ:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000368 return path
Guido van Rossumd8faa362007-04-27 19:54:29 +0000369 else:
370 try:
371 drive = os.environ['HOMEDRIVE']
372 except KeyError:
373 drive = ''
374 userhome = join(drive, os.environ['HOMEPATH'])
375
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000376 if isinstance(path, bytes):
377 userhome = userhome.encode(sys.getfilesystemencoding())
378
Guido van Rossumd8faa362007-04-27 19:54:29 +0000379 if i != 1: #~user
380 userhome = join(dirname(userhome), path[1:i])
381
Guido van Rossum15e22e11997-12-05 19:03:01 +0000382 return userhome + path[i:]
Guido van Rossum555915a1994-02-24 11:32:59 +0000383
384
385# Expand paths containing shell variable substitutions.
386# The following rules apply:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000387# - no expansion within single quotes
Guido van Rossumd8faa362007-04-27 19:54:29 +0000388# - '$$' is translated into '$'
389# - '%%' is translated into '%' if '%%' are not seen in %var1%%var2%
Guido van Rossum15e22e11997-12-05 19:03:01 +0000390# - ${varname} is accepted.
Guido van Rossumd8faa362007-04-27 19:54:29 +0000391# - $varname is accepted.
392# - %varname% is accepted.
393# - varnames can be made out of letters, digits and the characters '_-'
Ezio Melotti13925002011-03-16 11:05:33 +0200394# (though is not verified in the ${varname} and %varname% cases)
Guido van Rossum555915a1994-02-24 11:32:59 +0000395# XXX With COMMAND.COM you can use any characters in a variable name,
396# XXX except '^|<>='.
397
Tim Peters2344fae2001-01-15 00:50:52 +0000398def expandvars(path):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000399 """Expand shell variables of the forms $var, ${var} and %var%.
Guido van Rossum534972b1999-02-03 17:20:50 +0000400
401 Unknown variables are left unchanged."""
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000402 if isinstance(path, bytes):
403 if ord('$') not in path and ord('%') not in path:
404 return path
405 import string
406 varchars = bytes(string.ascii_letters + string.digits + '_-', 'ascii')
Amaury Forgeot d'Arc3b44e612008-10-03 20:32:33 +0000407 quote = b'\''
408 percent = b'%'
409 brace = b'{'
410 dollar = b'$'
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000411 else:
412 if '$' not in path and '%' not in path:
413 return path
414 import string
415 varchars = string.ascii_letters + string.digits + '_-'
Amaury Forgeot d'Arc3b44e612008-10-03 20:32:33 +0000416 quote = '\''
417 percent = '%'
418 brace = '{'
419 dollar = '$'
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000420 res = path[:0]
Guido van Rossum15e22e11997-12-05 19:03:01 +0000421 index = 0
422 pathlen = len(path)
423 while index < pathlen:
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000424 c = path[index:index+1]
Amaury Forgeot d'Arc3b44e612008-10-03 20:32:33 +0000425 if c == quote: # no expansion within single quotes
Guido van Rossum15e22e11997-12-05 19:03:01 +0000426 path = path[index + 1:]
427 pathlen = len(path)
428 try:
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000429 index = path.index(c)
Georg Brandl599b65d2010-07-23 08:46:35 +0000430 res += c + path[:index + 1]
Fred Drakeb4e460a2000-09-28 16:25:20 +0000431 except ValueError:
Georg Brandl599b65d2010-07-23 08:46:35 +0000432 res += path
Fred Drakeb4e460a2000-09-28 16:25:20 +0000433 index = pathlen - 1
Amaury Forgeot d'Arc3b44e612008-10-03 20:32:33 +0000434 elif c == percent: # variable or '%'
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000435 if path[index + 1:index + 2] == percent:
Georg Brandl599b65d2010-07-23 08:46:35 +0000436 res += c
437 index += 1
Guido van Rossumd8faa362007-04-27 19:54:29 +0000438 else:
439 path = path[index+1:]
440 pathlen = len(path)
441 try:
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000442 index = path.index(percent)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000443 except ValueError:
Georg Brandl599b65d2010-07-23 08:46:35 +0000444 res += percent + path
Guido van Rossumd8faa362007-04-27 19:54:29 +0000445 index = pathlen - 1
446 else:
447 var = path[:index]
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000448 if isinstance(path, bytes):
449 var = var.decode('ascii')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000450 if var in os.environ:
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000451 value = os.environ[var]
Guido van Rossumd8faa362007-04-27 19:54:29 +0000452 else:
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000453 value = '%' + var + '%'
454 if isinstance(path, bytes):
455 value = value.encode('ascii')
Georg Brandl599b65d2010-07-23 08:46:35 +0000456 res += value
Amaury Forgeot d'Arc3b44e612008-10-03 20:32:33 +0000457 elif c == dollar: # variable or '$$'
458 if path[index + 1:index + 2] == dollar:
Georg Brandl599b65d2010-07-23 08:46:35 +0000459 res += c
460 index += 1
Amaury Forgeot d'Arc3b44e612008-10-03 20:32:33 +0000461 elif path[index + 1:index + 2] == brace:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000462 path = path[index+2:]
463 pathlen = len(path)
464 try:
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000465 if isinstance(path, bytes):
466 index = path.index(b'}')
Thomas Woutersb2137042007-02-01 18:02:27 +0000467 else:
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000468 index = path.index('}')
469 var = path[:index]
470 if isinstance(path, bytes):
471 var = var.decode('ascii')
472 if var in os.environ:
473 value = os.environ[var]
474 else:
475 value = '${' + var + '}'
476 if isinstance(path, bytes):
477 value = value.encode('ascii')
Georg Brandl599b65d2010-07-23 08:46:35 +0000478 res += value
Fred Drakeb4e460a2000-09-28 16:25:20 +0000479 except ValueError:
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000480 if isinstance(path, bytes):
Georg Brandl599b65d2010-07-23 08:46:35 +0000481 res += b'${' + path
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000482 else:
Georg Brandl599b65d2010-07-23 08:46:35 +0000483 res += '${' + path
Guido van Rossum15e22e11997-12-05 19:03:01 +0000484 index = pathlen - 1
485 else:
486 var = ''
Georg Brandl599b65d2010-07-23 08:46:35 +0000487 index += 1
Guido van Rossum15e22e11997-12-05 19:03:01 +0000488 c = path[index:index + 1]
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000489 while c and c in varchars:
490 if isinstance(path, bytes):
Georg Brandl599b65d2010-07-23 08:46:35 +0000491 var += c.decode('ascii')
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000492 else:
Georg Brandl599b65d2010-07-23 08:46:35 +0000493 var += c
494 index += 1
Guido van Rossum15e22e11997-12-05 19:03:01 +0000495 c = path[index:index + 1]
Raymond Hettinger54f02222002-06-01 14:18:47 +0000496 if var in os.environ:
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000497 value = os.environ[var]
Thomas Woutersb2137042007-02-01 18:02:27 +0000498 else:
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000499 value = '$' + var
500 if isinstance(path, bytes):
501 value = value.encode('ascii')
Georg Brandl599b65d2010-07-23 08:46:35 +0000502 res += value
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000503 if c:
Georg Brandl599b65d2010-07-23 08:46:35 +0000504 index -= 1
Guido van Rossum15e22e11997-12-05 19:03:01 +0000505 else:
Georg Brandl599b65d2010-07-23 08:46:35 +0000506 res += c
507 index += 1
Guido van Rossum15e22e11997-12-05 19:03:01 +0000508 return res
Guido van Rossum555915a1994-02-24 11:32:59 +0000509
510
Tim Peters54a14a32001-08-30 22:05:26 +0000511# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A\B.
Guido van Rossum3df7b5a1996-08-26 16:35:26 +0000512# Previously, this function also truncated pathnames to 8+3 format,
513# but as this module is called "ntpath", that's obviously wrong!
Guido van Rossum555915a1994-02-24 11:32:59 +0000514
515def normpath(path):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000516 """Normalize path, eliminating double slashes, etc."""
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000517 sep = _get_sep(path)
Amaury Forgeot d'Arc3b44e612008-10-03 20:32:33 +0000518 dotdot = _get_dot(path) * 2
Georg Brandlcfb68212010-07-31 21:40:15 +0000519 special_prefixes = _get_special(path)
520 if path.startswith(special_prefixes):
521 # in the case of paths with these prefixes:
522 # \\.\ -> device names
523 # \\?\ -> literal paths
524 # do not do any normalization, but return the path unchanged
525 return path
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000526 path = path.replace(_get_altsep(path), sep)
Guido van Rossum15e22e11997-12-05 19:03:01 +0000527 prefix, path = splitdrive(path)
Mark Hammond5a607a32009-05-06 08:04:54 +0000528
529 # collapse initial backslashes
530 if path.startswith(sep):
Georg Brandl599b65d2010-07-23 08:46:35 +0000531 prefix += sep
Mark Hammond5a607a32009-05-06 08:04:54 +0000532 path = path.lstrip(sep)
533
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000534 comps = path.split(sep)
Guido van Rossum15e22e11997-12-05 19:03:01 +0000535 i = 0
536 while i < len(comps):
Amaury Forgeot d'Arc3b44e612008-10-03 20:32:33 +0000537 if not comps[i] or comps[i] == _get_dot(path):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000538 del comps[i]
Amaury Forgeot d'Arc3b44e612008-10-03 20:32:33 +0000539 elif comps[i] == dotdot:
540 if i > 0 and comps[i-1] != dotdot:
Tim Peters54a14a32001-08-30 22:05:26 +0000541 del comps[i-1:i+1]
542 i -= 1
Amaury Forgeot d'Arc3b44e612008-10-03 20:32:33 +0000543 elif i == 0 and prefix.endswith(_get_sep(path)):
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000544 del comps[i]
545 else:
546 i += 1
Guido van Rossum15e22e11997-12-05 19:03:01 +0000547 else:
Tim Peters54a14a32001-08-30 22:05:26 +0000548 i += 1
Guido van Rossum15e22e11997-12-05 19:03:01 +0000549 # If the path is now empty, substitute '.'
550 if not prefix and not comps:
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000551 comps.append(_get_dot(path))
552 return prefix + sep.join(comps)
Guido van Rossume294cf61999-01-29 18:05:18 +0000553
554
555# Return an absolute path.
Thomas Wouters477c8d52006-05-27 19:21:47 +0000556try:
557 from nt import _getfullpathname
Mark Hammondf717f052002-01-17 00:44:26 +0000558
Thomas Wouters477c8d52006-05-27 19:21:47 +0000559except ImportError: # not running on Windows - mock up something sensible
560 def abspath(path):
561 """Return the absolute version of a path."""
562 if not isabs(path):
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000563 if isinstance(path, bytes):
564 cwd = os.getcwdb()
565 else:
566 cwd = os.getcwd()
567 path = join(cwd, path)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000568 return normpath(path)
569
570else: # use native Windows method on Windows
571 def abspath(path):
572 """Return the absolute version of a path."""
573
574 if path: # Empty path must return current working directory.
575 try:
576 path = _getfullpathname(path)
577 except WindowsError:
578 pass # Bad path - return unchanged.
Florent Xiclunaad8c5ca2010-03-08 14:44:41 +0000579 elif isinstance(path, bytes):
580 path = os.getcwdb()
Thomas Wouters477c8d52006-05-27 19:21:47 +0000581 else:
582 path = os.getcwd()
583 return normpath(path)
Guido van Rossum83eeef42001-09-17 15:16:09 +0000584
585# realpath is a no-op on systems without islink support
586realpath = abspath
Mark Hammond8696ebc2002-10-08 02:44:31 +0000587# Win9x family and earlier have no Unicode filename support.
Tim Peters26bc25a2002-10-09 07:56:04 +0000588supports_unicode_filenames = (hasattr(sys, "getwindowsversion") and
589 sys.getwindowsversion()[3] >= 2)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000590
591def relpath(path, start=curdir):
592 """Return a relative version of a path"""
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000593 sep = _get_sep(path)
594
595 if start is curdir:
596 start = _get_dot(path)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000597
598 if not path:
599 raise ValueError("no path specified")
Mark Hammond5a607a32009-05-06 08:04:54 +0000600
601 start_abs = abspath(normpath(start))
602 path_abs = abspath(normpath(path))
603 start_drive, start_rest = splitdrive(start_abs)
604 path_drive, path_rest = splitdrive(path_abs)
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000605 if normcase(start_drive) != normcase(path_drive):
Mark Hammond5a607a32009-05-06 08:04:54 +0000606 error = "path is on mount '{0}', start on mount '{1}'".format(
607 path_drive, start_drive)
608 raise ValueError(error)
609
610 start_list = [x for x in start_rest.split(sep) if x]
611 path_list = [x for x in path_rest.split(sep) if x]
Guido van Rossumd8faa362007-04-27 19:54:29 +0000612 # Work out how much of the filepath is shared by start and path.
Mark Hammond5a607a32009-05-06 08:04:54 +0000613 i = 0
614 for e1, e2 in zip(start_list, path_list):
Hirokazu Yamamotob08820a2010-10-18 12:13:18 +0000615 if normcase(e1) != normcase(e2):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000616 break
Guido van Rossumd8faa362007-04-27 19:54:29 +0000617 i += 1
618
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000619 if isinstance(path, bytes):
620 pardir = b'..'
621 else:
622 pardir = '..'
Guido van Rossumd8faa362007-04-27 19:54:29 +0000623 rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
Christian Heimesfaf2f632008-01-06 16:59:19 +0000624 if not rel_list:
Amaury Forgeot d'Arcc72ef8b2008-10-03 18:38:26 +0000625 return _get_dot(path)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000626 return join(*rel_list)
Brian Curtind40e6f72010-07-08 21:39:08 +0000627
628
629# determine if two files are in fact the same file
Brian Curtin0dac8082010-09-23 20:38:14 +0000630try:
Brian Curtine8e80422010-09-24 13:56:34 +0000631 # GetFinalPathNameByHandle is available starting with Windows 6.0.
632 # Windows XP and non-Windows OS'es will mock _getfinalpathname.
633 if sys.getwindowsversion()[:2] >= (6, 0):
634 from nt import _getfinalpathname
635 else:
636 raise ImportError
637except (AttributeError, ImportError):
Brian Curtin0dac8082010-09-23 20:38:14 +0000638 # On Windows XP and earlier, two files are the same if their absolute
639 # pathnames are the same.
Brian Curtine8e80422010-09-24 13:56:34 +0000640 # Non-Windows operating systems fake this method with an XP
641 # approximation.
Brian Curtin0dac8082010-09-23 20:38:14 +0000642 def _getfinalpathname(f):
Ronald Oussoren6355c162011-05-06 17:11:07 +0200643 return normcase(abspath(f))
Brian Curtin0dac8082010-09-23 20:38:14 +0000644
Brian Curtind40e6f72010-07-08 21:39:08 +0000645def samefile(f1, f2):
646 "Test whether two pathnames reference the same actual file"
Brian Curtin0dac8082010-09-23 20:38:14 +0000647 return _getfinalpathname(f1) == _getfinalpathname(f2)
648
649
650try:
651 from nt import _getfileinformation
652except ImportError:
653 # On other operating systems, just return the fd and see that
654 # it compares equal in sameopenfile.
655 def _getfileinformation(fd):
656 return fd
Brian Curtin62857742010-09-06 17:07:27 +0000657
658def sameopenfile(f1, f2):
659 """Test whether two file objects reference the same file"""
Brian Curtin0dac8082010-09-23 20:38:14 +0000660 return _getfileinformation(f1) == _getfileinformation(f2)
Brian Curtin9c669cc2011-06-08 18:17:18 -0500661
662
663try:
664 # The genericpath.isdir implementation uses os.stat and checks the mode
665 # attribute to tell whether or not the path is a directory.
666 # This is overkill on Windows - just pass the path to GetFileAttributes
667 # and check the attribute from there.
Brian Curtin95d028f2011-06-09 09:10:38 -0500668 from nt import _isdir as isdir
Brian Curtin9c669cc2011-06-08 18:17:18 -0500669except ImportError:
Brian Curtin95d028f2011-06-09 09:10:38 -0500670 # Use genericpath.isdir as imported above.
671 pass