1 # Module 'ntpath' -- common operations on WinNT/Win95 pathnames
2 """Common pathname manipulations, WindowsNT/95 version.
4 Instead of importing this module directly, import os and refer to this
12 __all__
= ["normcase","isabs","join","splitdrive","split","splitext",
13 "basename","dirname","commonprefix","getsize","getmtime",
14 "getatime","getctime", "islink","exists","isdir","isfile","ismount",
15 "walk","expanduser","expandvars","normpath","abspath","splitunc",
16 "curdir","pardir","sep","pathsep","defpath","altsep","extsep",
17 "realpath","supports_unicode_filenames"]
19 # strings representing various path-related bits and pieces
27 if 'ce' in sys
.builtin_module_names
:
29 elif 'os2' in sys
.builtin_module_names
:
33 # Normalize the case of a pathname and map slashes to backslashes.
34 # Other normalizations (such as optimizing '../' away) are not done
35 # (this is done by normpath).
38 """Normalize case of pathname.
40 Makes all characters lowercase and all slashes into backslashes."""
41 return s
.replace("/", "\\").lower()
44 # Return whether a path is absolute.
45 # 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
47 # volume), or if a pathname after the volume letter and colon / UNC resource
48 # starts with a slash or backslash.
51 """Test whether a path is absolute"""
53 return s
!= '' and s
[:1] in '/\\'
56 # Join two (or more) paths.
59 """Join two or more pathname components, inserting "\\" as needed"""
62 b_wins
= 0 # set to 1 iff b makes path irrelevant
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'
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.
79 # 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 "/\\"):
88 # Join, and ensure there's a separator.
91 if b
and b
[0] in "/\\":
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
112 # Split a path in a drive specification (a drive letter followed by a
113 # colon) and the path specification.
114 # It is always true that drivespec + pathspec == p
116 """Split a pathname into drive and path specifiers. Returns a 2-tuple
117 "(drive,path)"; either part may be empty"""
125 """Split a pathname into UNC mount point and relative path specifiers.
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.
133 return '', p
# Drive letter present
135 if firstTwo
== '//' or firstTwo
== '\\\\':
137 # vvvvvvvvvvvvvvvvvvvv equivalent to drive letter
138 # \\machine\mountpoint\directories...
139 # directory ^^^^^^^^^^^^^^^
141 index
= normp
.find('\\', 2)
143 ##raise RuntimeError, 'illegal UNC path: "' + p + '"'
145 index
= normp
.find('\\', index
+ 1)
148 return p
[:index
], p
[index
:]
152 # Split a path in head (everything up to the last '/') and tail (the
153 # rest). After the trailing '/' is stripped, the invariant
154 # join(head, tail) == p holds.
155 # The resulting head won't end in '/' unless it is the root.
160 Return tuple (head, tail) where tail is everything after the final slash.
161 Either part may be empty."""
164 # set i to index beyond p's last slash
166 while i
and p
[i
-1] not in '/\\':
168 head
, tail
= p
[:i
], p
[i
:] # now tail has no slashes
169 # remove trailing slashes from head, unless it's all slashes
171 while head2
and head2
[-1] in '/\\':
174 return d
+ head
, tail
177 # Split a path in root and extension.
178 # The extension is everything starting at the last dot in the last
179 # pathname component; the root is everything before that.
180 # It is always true that root + ext == p.
183 """Split the extension from a pathname.
185 Extension is everything from the last dot to the end.
186 Return (root, ext), either part may be empty."""
189 if i
<=max(p
.rfind('/'), p
.rfind('\\')):
195 # Return the tail (basename) part of a path.
198 """Returns the final component of a pathname"""
202 # Return the head (dirname) part of a path.
205 """Returns the directory component of a pathname"""
209 # Return the longest prefix of all list elements.
212 "Given a list of pathnames, returns the longest common leading component"
216 for i
in range(len(prefix
)):
217 if prefix
[:i
+1] != item
[:i
+1]:
224 # Get size, mtime, atime of files.
226 def getsize(filename
):
227 """Return the size of a file, reported by os.stat()"""
228 return os
.stat(filename
).st_size
230 def getmtime(filename
):
231 """Return the last modification time of a file, reported by os.stat()"""
232 return os
.stat(filename
).st_mtime
234 def getatime(filename
):
235 """Return the last access time of a file, reported by os.stat()"""
236 return os
.stat(filename
).st_atime
238 def getctime(filename
):
239 """Return the creation time of a file, reported by os.stat()."""
240 return os
.stat(filename
).st_ctime
242 # Is a path a symbolic link?
243 # This will always return false on systems where posix.lstat doesn't exist.
246 """Test for symbolic link. On WindowsNT/95 always returns false"""
251 # This is false for dangling symbolic links.
254 """Test whether a path exists"""
262 # Is a path a dos directory?
263 # This follows symbolic links, so both islink() and isdir() can be true
267 """Test whether a path is a directory"""
272 return stat
.S_ISDIR(st
.st_mode
)
275 # Is a path a regular file?
276 # This follows symbolic links, so both islink() and isdir() can be true
280 """Test whether a path is a regular file"""
285 return stat
.S_ISREG(st
.st_mode
)
288 # 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.
292 """Test whether a path is a mount point (defined as root of drive)"""
293 unc
, rest
= splitunc(path
)
295 return rest
in ("", "/", "\\")
296 p
= splitdrive(path
)[1]
297 return len(p
) == 1 and p
[0] in '/\\'
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
304 # of files (and subdirectories etc.) in the directory.
305 # The func may modify the filenames list, to implement a filter,
306 # or to impose a different order of visiting.
308 def walk(top
, func
, arg
):
309 """Directory tree walk with callback function.
311 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."""
324 names
= os
.listdir(top
)
327 func(arg
, top
, names
)
328 exceptions
= ('.', '..')
330 if name
not in exceptions
:
331 name
= join(top
, name
)
333 walk(name
, func
, arg
)
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.)
345 def expanduser(path
):
346 """Expand ~ and ~user constructs.
348 If user or $HOME is unknown, do nothing."""
352 while i
< n
and path
[i
] not in '/\\':
355 if 'HOME' in os
.environ
:
356 userhome
= os
.environ
['HOME']
357 elif not 'HOMEPATH' in os
.environ
:
361 drive
= os
.environ
['HOMEDRIVE']
364 userhome
= join(drive
, os
.environ
['HOMEPATH'])
367 return userhome
+ path
[i
:]
370 # Expand paths containing shell variable substitutions.
371 # The following rules apply:
372 # - 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 '_'
376 # XXX With COMMAND.COM you can use any characters in a variable name,
377 # XXX except '^|<>='.
379 def expandvars(path
):
380 """Expand shell variables of form $var and ${var}.
382 Unknown variables are left unchanged."""
386 varchars
= string
.ascii_letters
+ string
.digits
+ '_-'
390 while index
< pathlen
:
392 if c
== '\'': # no expansion within single quotes
393 path
= path
[index
+ 1:]
396 index
= path
.index('\'')
397 res
= res
+ '\'' + path
[:index
+ 1]
401 elif c
== '$': # variable or '$$'
402 if path
[index
+ 1:index
+ 2] == '$':
405 elif path
[index
+ 1:index
+ 2] == '{':
406 path
= path
[index
+2:]
409 index
= path
.index('}')
411 if var
in os
.environ
:
412 res
= res
+ os
.environ
[var
]
419 c
= path
[index
:index
+ 1]
420 while c
!= '' and c
in varchars
:
423 c
= path
[index
:index
+ 1]
424 if var
in os
.environ
:
425 res
= res
+ os
.environ
[var
]
434 # Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A\B.
435 # Previously, this function also truncated pathnames to 8+3 format,
436 # but as this module is called "ntpath", that's obviously wrong!
439 """Normalize path, eliminating double slashes, etc."""
440 path
= path
.replace("/", "\\")
441 prefix
, path
= splitdrive(path
)
442 while path
[:1] == "\\":
443 prefix
= prefix
+ "\\"
445 comps
= path
.split("\\")
447 while i
< len(comps
):
448 if comps
[i
] in ('.', ''):
450 elif comps
[i
] == '..':
451 if i
> 0 and comps
[i
-1] != '..':
454 elif i
== 0 and prefix
.endswith("\\"):
460 # If the path is now empty, substitute '.'
461 if not prefix
and not comps
:
463 return prefix
+ "\\".join(comps
)
466 # Return an absolute path.
468 """Return the absolute version of a path"""
470 from nt
import _getfullpathname
471 except ImportError: # Not running on Windows - mock up something sensible.
475 path
= join(os
.getcwd(), path
)
476 return normpath(path
)
478 return _abspath(path
)
480 if path
: # Empty path must return current working directory.
482 path
= _getfullpathname(path
)
484 pass # Bad path - return unchanged.
487 return normpath(path
)
489 # realpath is a no-op on systems without islink support
491 # Win9x family and earlier have no Unicode filename support.
492 supports_unicode_filenames
= (hasattr(sys
, "getwindowsversion") and
493 sys
.getwindowsversion()[3] >= 2)