1 """Common operations on DOS pathnames."""
6 __all__
= ["normcase","isabs","join","splitdrive","split","splitext",
7 "basename","dirname","commonprefix","getsize","getmtime",
8 "getatime","islink","exists","isdir","isfile","ismount",
9 "walk","expanduser","expandvars","normpath","abspath"]
12 """Normalize the case of a pathname.
13 On MS-DOS it maps the pathname to lowercase, turns slashes into
15 Other normalizations (such as optimizing '../' away) are not allowed
16 (this is done by normpath).
17 Previously, this version mapped invalid consecutive characters to a
18 single '_', but this has been removed. This functionality should
19 possibly be added as a new function."""
21 return s
.replace("/", "\\").lower()
25 """Return whether a path is absolute.
26 Trivial in Posix, harder on the Mac or MS-DOS.
27 For DOS it is absolute if it starts with a slash or backslash (current
28 volume), or if a pathname after the volume letter and colon starts with
29 a slash or backslash."""
32 return s
!= '' and s
[:1] in '/\\'
36 """Join two (or more) paths."""
42 elif path
== '' or path
[-1:] in '/\\:':
45 path
= path
+ "\\" + b
50 """Split a path into a drive specification (a drive letter followed
51 by a colon) and path specification.
52 It is always true that drivespec + pathspec == p."""
60 """Split a path into head (everything up to the last '/') and tail
61 (the rest). After the trailing '/' is stripped, the invariant
62 join(head, tail) == p holds.
63 The resulting head won't end in '/' unless it is the root."""
66 # set i to index beyond p's last slash
68 while i
and p
[i
-1] not in '/\\':
70 head
, tail
= p
[:i
], p
[i
:] # now tail has no slashes
71 # remove trailing slashes from head, unless it's all slashes
73 while head2
and head2
[-1] in '/\\':
80 """Split a path into root and extension.
81 The extension is everything starting at the first dot in the last
82 pathname component; the root is everything before that.
83 It is always true that root + ext == p."""
88 root
, ext
= root
+ ext
+ c
, ''
97 """Return the tail (basename) part of a path."""
103 """Return the head (dirname) part of a path."""
109 """Return the longest prefix of all list elements."""
114 for i
in range(len(prefix
)):
115 if prefix
[:i
+1] != item
[:i
+1]:
122 # Get size, mtime, atime of files.
124 def getsize(filename
):
125 """Return the size of a file, reported by os.stat()."""
126 return os
.stat(filename
).st_size
128 def getmtime(filename
):
129 """Return the last modification time of a file, reported by os.stat()."""
130 return os
.stat(filename
).st_mtime
132 def getatime(filename
):
133 """Return the last access time of a file, reported by os.stat()."""
135 return os
.stat(filename
).st_atime
138 """Is a path a symbolic link?
139 This will always return false on systems where posix.lstat doesn't exist."""
145 """Does a path exist?
146 This is false for dangling symbolic links."""
156 """Is a path a dos directory?"""
162 return stat
.S_ISDIR(st
.st_mode
)
166 """Is a path a regular file?"""
172 return stat
.S_ISREG(st
.st_mode
)
176 """Is a path a mount point?"""
177 # XXX This degenerates in: 'is this the root?' on DOS
179 return isabs(splitdrive(path
)[1])
182 def walk(top
, func
, arg
):
183 """Directory tree walk with callback function.
185 For each directory in the directory tree rooted at top (including top
186 itself, but excluding '.' and '..'), call func(arg, dirname, fnames).
187 dirname is the name of the directory, and fnames a list of the names of
188 the files and subdirectories in dirname (excluding '.' and '..'). func
189 may modify the fnames list in-place (e.g. via del or slice assignment),
190 and walk will only recurse into the subdirectories whose names remain in
191 fnames; this can be used to implement a filter, or to impose a specific
192 order of visiting. No semantics are defined for, or required of, arg,
193 beyond that arg is always passed to func. It can be used, e.g., to pass
194 a filename pattern, or a mutable object designed to accumulate
195 statistics. Passing None for arg is common."""
198 names
= os
.listdir(top
)
201 func(arg
, top
, names
)
202 exceptions
= ('.', '..')
204 if name
not in exceptions
:
205 name
= join(top
, name
)
207 walk(name
, func
, arg
)
210 def expanduser(path
):
211 """Expand paths beginning with '~' or '~user'.
212 '~' means $HOME; '~user' means that user's home directory.
213 If the path doesn't begin with '~', or if the user or $HOME is unknown,
214 the path is returned unchanged (leaving error reporting to whatever
215 function is called with the expanded path as argument).
216 See also module 'glob' for expansion of *, ? and [...] in pathnames.
217 (A function should also be defined to do full *sh-style environment
218 variable expansion.)"""
223 while i
< n
and path
[i
] not in '/\\':
226 if not 'HOME' in os
.environ
:
228 userhome
= os
.environ
['HOME']
231 return userhome
+ path
[i
:]
234 def expandvars(path
):
235 """Expand paths containing shell variable substitutions.
236 The following rules apply:
237 - no expansion within single quotes
238 - no escape character, except for '$$' which is translated into '$'
239 - ${varname} is accepted.
240 - varnames can be made out of letters, digits and the character '_'"""
241 # XXX With COMMAND.COM you can use any characters in a variable name,
242 # XXX except '^|<>='.
247 varchars
= string
.ascii_letters
+ string
.digits
+ "_-"
251 while index
< pathlen
:
253 if c
== '\'': # no expansion within single quotes
254 path
= path
[index
+ 1:]
257 index
= path
.index('\'')
258 res
= res
+ '\'' + path
[:index
+ 1]
262 elif c
== '$': # variable or '$$'
263 if path
[index
+ 1:index
+ 2] == '$':
266 elif path
[index
+ 1:index
+ 2] == '{':
267 path
= path
[index
+2:]
270 index
= path
.index('}')
272 if var
in os
.environ
:
273 res
= res
+ os
.environ
[var
]
280 c
= path
[index
:index
+ 1]
281 while c
!= '' and c
in varchars
:
284 c
= path
[index
:index
+ 1]
285 if var
in os
.environ
:
286 res
= res
+ os
.environ
[var
]
296 """Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.
297 Also, components of the path are silently truncated to 8+3 notation."""
299 path
= path
.replace("/", "\\")
300 prefix
, path
= splitdrive(path
)
301 while path
[:1] == "\\":
302 prefix
= prefix
+ "\\"
304 comps
= path
.split("\\")
306 while i
< len(comps
):
309 elif comps
[i
] == '..' and i
> 0 and \
310 comps
[i
-1] not in ('', '..'):
313 elif comps
[i
] == '' and i
> 0 and comps
[i
-1] != '':
315 elif '.' in comps
[i
]:
316 comp
= comps
[i
].split('.')
317 comps
[i
] = comp
[0][:8] + '.' + comp
[1][:3]
319 elif len(comps
[i
]) > 8:
320 comps
[i
] = comps
[i
][:8]
324 # If the path is now empty, substitute '.'
325 if not prefix
and not comps
:
327 return prefix
+ "\\".join(comps
)
332 """Return an absolute path."""
334 path
= join(os
.getcwd(), path
)
335 return normpath(path
)
337 # realpath is a no-op on systems without islink support