blob: 687d88513e2051dab276bb4fe3f1b7d83c7b85dd [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
9import stat
Mark Hammond8696ebc2002-10-08 02:44:31 +000010import sys
Skip Montanaro4d5d5bf2000-07-13 01:01:03 +000011
Skip Montanaro269b83b2001-02-06 01:07:02 +000012__all__ = ["normcase","isabs","join","splitdrive","split","splitext",
13 "basename","dirname","commonprefix","getsize","getmtime",
Martin v. Löwis96a60e42002-12-31 13:11:54 +000014 "getatime","getctime", "islink","exists","isdir","isfile","ismount",
Mark Hammond8696ebc2002-10-08 02:44:31 +000015 "walk","expanduser","expandvars","normpath","abspath","splitunc",
Skip Montanaro117910d2003-02-14 19:35:31 +000016 "curdir","pardir","sep","pathsep","defpath","altsep","extsep",
Neal Norwitz61cdac62003-01-03 18:01:57 +000017 "realpath","supports_unicode_filenames"]
Guido van Rossum555915a1994-02-24 11:32:59 +000018
Skip Montanaro117910d2003-02-14 19:35:31 +000019# strings representing various path-related bits and pieces
20curdir = '.'
21pardir = '..'
22extsep = '.'
23sep = '\\'
24pathsep = ';'
Skip Montanaro9ddac3e2003-03-28 22:23:24 +000025altsep = '/'
Andrew MacIntyre437966c2003-02-17 09:17:50 +000026defpath = '.;C:\\bin'
Skip Montanaro117910d2003-02-14 19:35:31 +000027if 'ce' in sys.builtin_module_names:
28 defpath = '\\Windows'
29elif 'os2' in sys.builtin_module_names:
Andrew MacIntyre437966c2003-02-17 09:17:50 +000030 # OS/2 w/ VACPP
Skip Montanaro117910d2003-02-14 19:35:31 +000031 altsep = '/'
Skip Montanaro117910d2003-02-14 19:35:31 +000032
Guido van Rossume2ad88c1997-08-12 14:46:58 +000033# Normalize the case of a pathname and map slashes to backslashes.
34# Other normalizations (such as optimizing '../' away) are not done
Guido van Rossum555915a1994-02-24 11:32:59 +000035# (this is done by normpath).
Guido van Rossume2ad88c1997-08-12 14:46:58 +000036
Guido van Rossum555915a1994-02-24 11:32:59 +000037def normcase(s):
Guido van Rossum16a0bc21998-02-18 13:48:31 +000038 """Normalize case of pathname.
39
Guido van Rossum534972b1999-02-03 17:20:50 +000040 Makes all characters lowercase and all slashes into backslashes."""
Fred Drakeb4e460a2000-09-28 16:25:20 +000041 return s.replace("/", "\\").lower()
Guido van Rossum555915a1994-02-24 11:32:59 +000042
Guido van Rossum77e1db31997-06-02 23:11:57 +000043
Fred Drakeef0b5dd2000-02-17 17:30:40 +000044# Return whether a path is absolute.
Guido van Rossum555915a1994-02-24 11:32:59 +000045# Trivial in Posix, harder on the Mac or MS-DOS.
46# For DOS it is absolute if it starts with a slash or backslash (current
Guido van Rossum534972b1999-02-03 17:20:50 +000047# volume), or if a pathname after the volume letter and colon / UNC resource
48# starts with a slash or backslash.
Guido van Rossum555915a1994-02-24 11:32:59 +000049
50def isabs(s):
Guido van Rossum15e22e11997-12-05 19:03:01 +000051 """Test whether a path is absolute"""
52 s = splitdrive(s)[1]
53 return s != '' and s[:1] in '/\\'
Guido van Rossum555915a1994-02-24 11:32:59 +000054
55
Guido van Rossum77e1db31997-06-02 23:11:57 +000056# Join two (or more) paths.
57
Barry Warsaw384d2491997-02-18 21:53:25 +000058def join(a, *p):
Guido van Rossum15e22e11997-12-05 19:03:01 +000059 """Join two or more pathname components, inserting "\\" as needed"""
60 path = a
61 for b in p:
Tim Peters33dc0a12001-07-27 08:09:54 +000062 b_wins = 0 # set to 1 iff b makes path irrelevant
63 if path == "":
64 b_wins = 1
Tim Peters1bdd0f22001-07-19 17:18:18 +000065
Tim Peters33dc0a12001-07-27 08:09:54 +000066 elif isabs(b):
67 # This probably wipes out path so far. However, it's more
68 # complicated if path begins with a drive letter:
69 # 1. join('c:', '/a') == 'c:/a'
70 # 2. join('c:/', '/a') == 'c:/a'
71 # But
72 # 3. join('c:/a', '/b') == '/b'
73 # 4. join('c:', 'd:/') = 'd:/'
74 # 5. join('c:/', 'd:/') = 'd:/'
75 if path[1:2] != ":" or b[1:2] == ":":
76 # Path doesn't start with a drive letter, or cases 4 and 5.
77 b_wins = 1
Tim Peters1bdd0f22001-07-19 17:18:18 +000078
Tim Peters33dc0a12001-07-27 08:09:54 +000079 # Else path has a drive letter, and b doesn't but is absolute.
80 elif len(path) > 3 or (len(path) == 3 and
81 path[-1] not in "/\\"):
82 # case 3
83 b_wins = 1
Tim Peters1bdd0f22001-07-19 17:18:18 +000084
Tim Peters33dc0a12001-07-27 08:09:54 +000085 if b_wins:
86 path = b
87 else:
88 # Join, and ensure there's a separator.
89 assert len(path) > 0
90 if path[-1] in "/\\":
91 if b and b[0] in "/\\":
92 path += b[1:]
93 else:
94 path += b
95 elif path[-1] == ":":
96 path += b
97 elif b:
98 if b[0] in "/\\":
99 path += b
100 else:
101 path += "\\" + b
Tim Peters6a3e5f12001-11-05 21:25:02 +0000102 else:
103 # path is not empty and does not end with a backslash,
104 # but b is empty; since, e.g., split('a/') produces
105 # ('a', ''), it's best if join() adds a backslash in
106 # this case.
107 path += '\\'
Tim Peters1bdd0f22001-07-19 17:18:18 +0000108
Guido van Rossum15e22e11997-12-05 19:03:01 +0000109 return path
Guido van Rossum555915a1994-02-24 11:32:59 +0000110
111
112# Split a path in a drive specification (a drive letter followed by a
Guido van Rossumf3c695c1999-04-06 19:32:19 +0000113# colon) and the path specification.
Guido van Rossum555915a1994-02-24 11:32:59 +0000114# It is always true that drivespec + pathspec == p
115def splitdrive(p):
Guido van Rossumf3c695c1999-04-06 19:32:19 +0000116 """Split a pathname into drive and path specifiers. Returns a 2-tuple
117"(drive,path)"; either part may be empty"""
Guido van Rossum15e22e11997-12-05 19:03:01 +0000118 if p[1:2] == ':':
119 return p[0:2], p[2:]
Guido van Rossumf3c695c1999-04-06 19:32:19 +0000120 return '', p
121
122
123# Parse UNC paths
124def splitunc(p):
125 """Split a pathname into UNC mount point and relative path specifiers.
126
127 Return a 2-tuple (unc, rest); either part may be empty.
128 If unc is not empty, it has the form '//host/mount' (or similar
129 using backslashes). unc+rest is always the input path.
130 Paths containing drive letters never have an UNC part.
131 """
132 if p[1:2] == ':':
133 return '', p # Drive letter present
Guido van Rossum534972b1999-02-03 17:20:50 +0000134 firstTwo = p[0:2]
135 if firstTwo == '//' or firstTwo == '\\\\':
136 # is a UNC path:
137 # vvvvvvvvvvvvvvvvvvvv equivalent to drive letter
138 # \\machine\mountpoint\directories...
139 # directory ^^^^^^^^^^^^^^^
140 normp = normcase(p)
Fred Drakeb4e460a2000-09-28 16:25:20 +0000141 index = normp.find('\\', 2)
Guido van Rossum534972b1999-02-03 17:20:50 +0000142 if index == -1:
143 ##raise RuntimeError, 'illegal UNC path: "' + p + '"'
144 return ("", p)
Fred Drakeb4e460a2000-09-28 16:25:20 +0000145 index = normp.find('\\', index + 1)
Guido van Rossum534972b1999-02-03 17:20:50 +0000146 if index == -1:
147 index = len(p)
148 return p[:index], p[index:]
Guido van Rossum15e22e11997-12-05 19:03:01 +0000149 return '', p
Guido van Rossum555915a1994-02-24 11:32:59 +0000150
151
152# Split a path in head (everything up to the last '/') and tail (the
Guido van Rossum8f0fa9e1999-03-19 21:05:12 +0000153# rest). After the trailing '/' is stripped, the invariant
Guido van Rossum555915a1994-02-24 11:32:59 +0000154# join(head, tail) == p holds.
155# The resulting head won't end in '/' unless it is the root.
156
157def split(p):
Guido van Rossum534972b1999-02-03 17:20:50 +0000158 """Split a pathname.
159
160 Return tuple (head, tail) where tail is everything after the final slash.
161 Either part may be empty."""
Guido van Rossum8f0fa9e1999-03-19 21:05:12 +0000162
Guido van Rossum15e22e11997-12-05 19:03:01 +0000163 d, p = splitdrive(p)
Guido van Rossum8f0fa9e1999-03-19 21:05:12 +0000164 # set i to index beyond p's last slash
165 i = len(p)
166 while i and p[i-1] not in '/\\':
167 i = i - 1
168 head, tail = p[:i], p[i:] # now tail has no slashes
169 # remove trailing slashes from head, unless it's all slashes
170 head2 = head
171 while head2 and head2[-1] in '/\\':
172 head2 = head2[:-1]
173 head = head2 or head
Guido van Rossum15e22e11997-12-05 19:03:01 +0000174 return d + head, tail
Guido van Rossum555915a1994-02-24 11:32:59 +0000175
176
177# Split a path in root and extension.
Guido van Rossum73e122f1997-01-22 00:17:26 +0000178# The extension is everything starting at the last dot in the last
Guido van Rossum555915a1994-02-24 11:32:59 +0000179# pathname component; the root is everything before that.
180# It is always true that root + ext == p.
181
182def splitext(p):
Guido van Rossum534972b1999-02-03 17:20:50 +0000183 """Split the extension from a pathname.
184
185 Extension is everything from the last dot to the end.
186 Return (root, ext), either part may be empty."""
Martin v. Löwisde333792002-12-12 20:30:20 +0000187
188 i = p.rfind('.')
189 if i<=max(p.rfind('/'), p.rfind('\\')):
190 return p, ''
191 else:
192 return p[:i], p[i:]
Guido van Rossum555915a1994-02-24 11:32:59 +0000193
194
195# Return the tail (basename) part of a path.
196
197def basename(p):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000198 """Returns the final component of a pathname"""
199 return split(p)[1]
Guido van Rossum555915a1994-02-24 11:32:59 +0000200
201
202# Return the head (dirname) part of a path.
203
204def dirname(p):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000205 """Returns the directory component of a pathname"""
206 return split(p)[0]
Guido van Rossum555915a1994-02-24 11:32:59 +0000207
208
209# Return the longest prefix of all list elements.
210
211def commonprefix(m):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000212 "Given a list of pathnames, returns the longest common leading component"
213 if not m: return ''
Skip Montanaro62358312000-08-22 13:01:53 +0000214 prefix = m[0]
215 for item in m:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000216 for i in range(len(prefix)):
Fred Drake8152d322000-12-12 23:20:45 +0000217 if prefix[:i+1] != item[:i+1]:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000218 prefix = prefix[:i]
219 if i == 0: return ''
220 break
Skip Montanaro62358312000-08-22 13:01:53 +0000221 return prefix
Guido van Rossum555915a1994-02-24 11:32:59 +0000222
223
Guido van Rossum2bc1f8f1998-07-24 20:49:26 +0000224# Get size, mtime, atime of files.
225
226def getsize(filename):
Guido van Rossum534972b1999-02-03 17:20:50 +0000227 """Return the size of a file, reported by os.stat()"""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000228 return os.stat(filename).st_size
Guido van Rossum2bc1f8f1998-07-24 20:49:26 +0000229
230def getmtime(filename):
Guido van Rossum534972b1999-02-03 17:20:50 +0000231 """Return the last modification time of a file, reported by os.stat()"""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000232 return os.stat(filename).st_mtime
Guido van Rossum2bc1f8f1998-07-24 20:49:26 +0000233
234def getatime(filename):
Guido van Rossum534972b1999-02-03 17:20:50 +0000235 """Return the last access time of a file, reported by os.stat()"""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000236 return os.stat(filename).st_atime
Guido van Rossum2bc1f8f1998-07-24 20:49:26 +0000237
Martin v. Löwis96a60e42002-12-31 13:11:54 +0000238def getctime(filename):
239 """Return the creation time of a file, reported by os.stat()."""
240 return os.stat(filename).st_ctime
Guido van Rossum2bc1f8f1998-07-24 20:49:26 +0000241
Guido van Rossum555915a1994-02-24 11:32:59 +0000242# Is a path a symbolic link?
243# This will always return false on systems where posix.lstat doesn't exist.
244
245def islink(path):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000246 """Test for symbolic link. On WindowsNT/95 always returns false"""
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000247 return False
Guido van Rossum555915a1994-02-24 11:32:59 +0000248
249
250# Does a path exist?
251# This is false for dangling symbolic links.
252
253def exists(path):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000254 """Test whether a path exists"""
255 try:
256 st = os.stat(path)
257 except os.error:
Tim Petersbc0e9102002-04-04 22:55:58 +0000258 return False
259 return True
Guido van Rossum555915a1994-02-24 11:32:59 +0000260
261
262# Is a path a dos directory?
263# This follows symbolic links, so both islink() and isdir() can be true
264# for the same path.
265
266def isdir(path):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000267 """Test whether a path is a directory"""
268 try:
269 st = os.stat(path)
270 except os.error:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000271 return False
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000272 return stat.S_ISDIR(st.st_mode)
Guido van Rossum555915a1994-02-24 11:32:59 +0000273
274
275# Is a path a regular file?
276# This follows symbolic links, so both islink() and isdir() can be true
277# for the same path.
278
279def isfile(path):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000280 """Test whether a path is a regular file"""
281 try:
282 st = os.stat(path)
283 except os.error:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000284 return False
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000285 return stat.S_ISREG(st.st_mode)
Guido van Rossum555915a1994-02-24 11:32:59 +0000286
287
Guido van Rossumf3c695c1999-04-06 19:32:19 +0000288# Is a path a mount point? Either a root (with or without drive letter)
289# or an UNC path with at most a / or \ after the mount point.
Guido van Rossum555915a1994-02-24 11:32:59 +0000290
291def ismount(path):
Guido van Rossumca99c2c1998-01-19 22:25:59 +0000292 """Test whether a path is a mount point (defined as root of drive)"""
Guido van Rossumf3c695c1999-04-06 19:32:19 +0000293 unc, rest = splitunc(path)
294 if unc:
295 return rest in ("", "/", "\\")
Guido van Rossumca99c2c1998-01-19 22:25:59 +0000296 p = splitdrive(path)[1]
Fred Drakeb4e460a2000-09-28 16:25:20 +0000297 return len(p) == 1 and p[0] in '/\\'
Guido van Rossum555915a1994-02-24 11:32:59 +0000298
299
300# Directory tree walk.
301# For each directory under top (including top itself, but excluding
302# '.' and '..'), func(arg, dirname, filenames) is called, where
303# dirname is the name of the directory and filenames is the list
Walter Dörwaldf0dfc7a2003-10-20 14:01:56 +0000304# of files (and subdirectories etc.) in the directory.
Guido van Rossum555915a1994-02-24 11:32:59 +0000305# The func may modify the filenames list, to implement a filter,
306# or to impose a different order of visiting.
307
308def walk(top, func, arg):
Tim Peterscf5e6a42001-10-10 04:16:20 +0000309 """Directory tree walk with callback function.
Guido van Rossum534972b1999-02-03 17:20:50 +0000310
Tim Peterscf5e6a42001-10-10 04:16:20 +0000311 For each directory in the directory tree rooted at top (including top
312 itself, but excluding '.' and '..'), call func(arg, dirname, fnames).
313 dirname is the name of the directory, and fnames a list of the names of
314 the files and subdirectories in dirname (excluding '.' and '..'). func
315 may modify the fnames list in-place (e.g. via del or slice assignment),
316 and walk will only recurse into the subdirectories whose names remain in
317 fnames; this can be used to implement a filter, or to impose a specific
318 order of visiting. No semantics are defined for, or required of, arg,
319 beyond that arg is always passed to func. It can be used, e.g., to pass
320 a filename pattern, or a mutable object designed to accumulate
321 statistics. Passing None for arg is common."""
322
Guido van Rossum15e22e11997-12-05 19:03:01 +0000323 try:
324 names = os.listdir(top)
325 except os.error:
326 return
327 func(arg, top, names)
328 exceptions = ('.', '..')
329 for name in names:
330 if name not in exceptions:
331 name = join(top, name)
332 if isdir(name):
333 walk(name, func, arg)
Guido van Rossum555915a1994-02-24 11:32:59 +0000334
335
336# Expand paths beginning with '~' or '~user'.
337# '~' means $HOME; '~user' means that user's home directory.
338# If the path doesn't begin with '~', or if the user or $HOME is unknown,
339# the path is returned unchanged (leaving error reporting to whatever
340# function is called with the expanded path as argument).
341# See also module 'glob' for expansion of *, ? and [...] in pathnames.
342# (A function should also be defined to do full *sh-style environment
343# variable expansion.)
344
345def expanduser(path):
Guido van Rossum534972b1999-02-03 17:20:50 +0000346 """Expand ~ and ~user constructs.
347
348 If user or $HOME is unknown, do nothing."""
Fred Drake8152d322000-12-12 23:20:45 +0000349 if path[:1] != '~':
Guido van Rossum15e22e11997-12-05 19:03:01 +0000350 return path
351 i, n = 1, len(path)
352 while i < n and path[i] not in '/\\':
Fred Drakeb4e460a2000-09-28 16:25:20 +0000353 i = i + 1
Guido van Rossum15e22e11997-12-05 19:03:01 +0000354 if i == 1:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000355 if 'HOME' in os.environ:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000356 userhome = os.environ['HOME']
Raymond Hettinger54f02222002-06-01 14:18:47 +0000357 elif not 'HOMEPATH' in os.environ:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000358 return path
359 else:
360 try:
Fred Drakeb4e460a2000-09-28 16:25:20 +0000361 drive = os.environ['HOMEDRIVE']
Guido van Rossum15e22e11997-12-05 19:03:01 +0000362 except KeyError:
363 drive = ''
364 userhome = join(drive, os.environ['HOMEPATH'])
365 else:
366 return path
367 return userhome + path[i:]
Guido van Rossum555915a1994-02-24 11:32:59 +0000368
369
370# Expand paths containing shell variable substitutions.
371# The following rules apply:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000372# - no expansion within single quotes
373# - no escape character, except for '$$' which is translated into '$'
374# - ${varname} is accepted.
375# - varnames can be made out of letters, digits and the character '_'
Guido van Rossum555915a1994-02-24 11:32:59 +0000376# XXX With COMMAND.COM you can use any characters in a variable name,
377# XXX except '^|<>='.
378
Tim Peters2344fae2001-01-15 00:50:52 +0000379def expandvars(path):
Guido van Rossum534972b1999-02-03 17:20:50 +0000380 """Expand shell variables of form $var and ${var}.
381
382 Unknown variables are left unchanged."""
Guido van Rossum15e22e11997-12-05 19:03:01 +0000383 if '$' not in path:
384 return path
Fred Drakeb4e460a2000-09-28 16:25:20 +0000385 import string
Fred Drake79e75e12001-07-20 19:05:50 +0000386 varchars = string.ascii_letters + string.digits + '_-'
Guido van Rossum15e22e11997-12-05 19:03:01 +0000387 res = ''
388 index = 0
389 pathlen = len(path)
390 while index < pathlen:
391 c = path[index]
392 if c == '\'': # no expansion within single quotes
393 path = path[index + 1:]
394 pathlen = len(path)
395 try:
Fred Drakeb4e460a2000-09-28 16:25:20 +0000396 index = path.index('\'')
Guido van Rossum15e22e11997-12-05 19:03:01 +0000397 res = res + '\'' + path[:index + 1]
Fred Drakeb4e460a2000-09-28 16:25:20 +0000398 except ValueError:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000399 res = res + path
Fred Drakeb4e460a2000-09-28 16:25:20 +0000400 index = pathlen - 1
Guido van Rossum15e22e11997-12-05 19:03:01 +0000401 elif c == '$': # variable or '$$'
402 if path[index + 1:index + 2] == '$':
403 res = res + c
404 index = index + 1
405 elif path[index + 1:index + 2] == '{':
406 path = path[index+2:]
407 pathlen = len(path)
408 try:
Fred Drakeb4e460a2000-09-28 16:25:20 +0000409 index = path.index('}')
Guido van Rossum15e22e11997-12-05 19:03:01 +0000410 var = path[:index]
Raymond Hettinger54f02222002-06-01 14:18:47 +0000411 if var in os.environ:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000412 res = res + os.environ[var]
Fred Drakeb4e460a2000-09-28 16:25:20 +0000413 except ValueError:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000414 res = res + path
415 index = pathlen - 1
416 else:
417 var = ''
418 index = index + 1
419 c = path[index:index + 1]
420 while c != '' and c in varchars:
421 var = var + c
422 index = index + 1
423 c = path[index:index + 1]
Raymond Hettinger54f02222002-06-01 14:18:47 +0000424 if var in os.environ:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000425 res = res + os.environ[var]
426 if c != '':
427 res = res + c
428 else:
429 res = res + c
430 index = index + 1
431 return res
Guido van Rossum555915a1994-02-24 11:32:59 +0000432
433
Tim Peters54a14a32001-08-30 22:05:26 +0000434# 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 +0000435# Previously, this function also truncated pathnames to 8+3 format,
436# but as this module is called "ntpath", that's obviously wrong!
Guido van Rossum555915a1994-02-24 11:32:59 +0000437
438def normpath(path):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000439 """Normalize path, eliminating double slashes, etc."""
Fred Drakeb4e460a2000-09-28 16:25:20 +0000440 path = path.replace("/", "\\")
Guido van Rossum15e22e11997-12-05 19:03:01 +0000441 prefix, path = splitdrive(path)
Fred Drakeb4e460a2000-09-28 16:25:20 +0000442 while path[:1] == "\\":
443 prefix = prefix + "\\"
Guido van Rossum15e22e11997-12-05 19:03:01 +0000444 path = path[1:]
Fred Drakeb4e460a2000-09-28 16:25:20 +0000445 comps = path.split("\\")
Guido van Rossum15e22e11997-12-05 19:03:01 +0000446 i = 0
447 while i < len(comps):
Tim Peters54a14a32001-08-30 22:05:26 +0000448 if comps[i] in ('.', ''):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000449 del comps[i]
Tim Peters54a14a32001-08-30 22:05:26 +0000450 elif comps[i] == '..':
451 if i > 0 and comps[i-1] != '..':
452 del comps[i-1:i+1]
453 i -= 1
454 elif i == 0 and prefix.endswith("\\"):
455 del comps[i]
456 else:
457 i += 1
Guido van Rossum15e22e11997-12-05 19:03:01 +0000458 else:
Tim Peters54a14a32001-08-30 22:05:26 +0000459 i += 1
Guido van Rossum15e22e11997-12-05 19:03:01 +0000460 # If the path is now empty, substitute '.'
461 if not prefix and not comps:
462 comps.append('.')
Fred Drakeb4e460a2000-09-28 16:25:20 +0000463 return prefix + "\\".join(comps)
Guido van Rossume294cf61999-01-29 18:05:18 +0000464
465
466# Return an absolute path.
467def abspath(path):
Guido van Rossum534972b1999-02-03 17:20:50 +0000468 """Return the absolute version of a path"""
Mark Hammondf717f052002-01-17 00:44:26 +0000469 try:
Mark Hammondef8b6542001-05-13 08:04:26 +0000470 from nt import _getfullpathname
Mark Hammondf717f052002-01-17 00:44:26 +0000471 except ImportError: # Not running on Windows - mock up something sensible.
472 global abspath
473 def _abspath(path):
474 if not isabs(path):
475 path = join(os.getcwd(), path)
476 return normpath(path)
477 abspath = _abspath
478 return _abspath(path)
479
480 if path: # Empty path must return current working directory.
Mark Hammond647d2fe2000-08-14 06:20:32 +0000481 try:
Mark Hammondef8b6542001-05-13 08:04:26 +0000482 path = _getfullpathname(path)
483 except WindowsError:
Fred Drakeda05e972001-05-15 15:23:01 +0000484 pass # Bad path - return unchanged.
Mark Hammond647d2fe2000-08-14 06:20:32 +0000485 else:
486 path = os.getcwd()
Guido van Rossum6dfc7921999-11-30 15:00:00 +0000487 return normpath(path)
Guido van Rossum83eeef42001-09-17 15:16:09 +0000488
489# realpath is a no-op on systems without islink support
490realpath = abspath
Mark Hammond8696ebc2002-10-08 02:44:31 +0000491# Win9x family and earlier have no Unicode filename support.
Tim Peters26bc25a2002-10-09 07:56:04 +0000492supports_unicode_filenames = (hasattr(sys, "getwindowsversion") and
493 sys.getwindowsversion()[3] >= 2)