1 """Common operations on Posix pathnames.
2
3 Instead of importing this module directly, import os and refer to
4 this module as os.path. The "os.path" name is an alias for this
5 module on Posix systems; on other systems (e.g. Mac, Windows),
6 os.path provides the same operations in a manner specific to that
7 platform, and is an alias to another module (e.g. macpath, ntpath).
8
9 Some of this can actually be useful on non-Posix systems too, e.g.
10 for manipulation of the pathname component of URLs.
11 """
12
13 import os
14 import sys
15 import stat
16 import genericpath
17 import warnings
18 from genericpath import *
19 from genericpath import _unicode
20
21 __all__ = ["normcase","isabs","join","splitdrive","split","splitext",
22 "basename","dirname","commonprefix","getsize","getmtime",
23 "getatime","getctime","islink","exists","lexists","isdir","isfile",
24 "ismount","walk","expanduser","expandvars","normpath","abspath",
25 "samefile","sameopenfile","samestat",
26 "curdir","pardir","sep","pathsep","defpath","altsep","extsep",
27 "devnull","realpath","supports_unicode_filenames","relpath"]
28
29
30 curdir = '.'
31 pardir = '..'
32 extsep = '.'
33 sep = '/'
34 pathsep = ':'
35 defpath = ':/bin:/usr/bin'
36 altsep = None
37 devnull = '/dev/null'
38
39
40
41
42
43
45 """Normalize case of pathname. Has no effect under Posix"""
46 return s
47
48
49
50
51
53 """Test whether a path is absolute"""
54 return s.startswith('/')
55
56
57
58
59
60
62 """Join two or more pathname components, inserting '/' as needed.
63 If any component is an absolute path, all previous path components
64 will be discarded. An empty last part will result in a path that
65 ends with a separator."""
66 path = a
67 for b in p:
68 if b.startswith('/'):
69 path = b
70 elif path == '' or path.endswith('/'):
71 path += b
72 else:
73 path += '/' + b
74 return path
75
76
77
78
79
80
81
83 """Split a pathname. Returns tuple "(head, tail)" where "tail" is
84 everything after the final slash. Either part may be empty."""
85 i = p.rfind('/') + 1
86 head, tail = p[:i], p[i:]
87 if head and head != '/'*len(head):
88 head = head.rstrip('/')
89 return head, tail
90
91
92
93
94
95
96
98 return genericpath._splitext(p, sep, altsep, extsep)
99 splitext.__doc__ = genericpath._splitext.__doc__
100
101
102
103
105 """Split a pathname into drive and path. On Posix, drive is always
106 empty."""
107 return '', p
108
109
110
111
113 """Returns the final component of a pathname"""
114 i = p.rfind('/') + 1
115 return p[i:]
116
117
118
119
121 """Returns the directory component of a pathname"""
122 i = p.rfind('/') + 1
123 head = p[:i]
124 if head and head != '/'*len(head):
125 head = head.rstrip('/')
126 return head
127
128
129
130
131
133 """Test whether a path is a symbolic link"""
134 try:
135 st = os.lstat(path)
136 except (os.error, AttributeError):
137 return False
138 return stat.S_ISLNK(st.st_mode)
139
140
141
143 """Test whether a path exists. Returns True for broken symbolic links"""
144 try:
145 os.lstat(path)
146 except os.error:
147 return False
148 return True
149
150
151
152
154 """Test whether two pathnames reference the same actual file"""
155 s1 = os.stat(f1)
156 s2 = os.stat(f2)
157 return samestat(s1, s2)
158
159
160
161
162
164 """Test whether two open file objects reference the same file"""
165 s1 = os.fstat(fp1)
166 s2 = os.fstat(fp2)
167 return samestat(s1, s2)
168
169
170
171
172
174 """Test whether two stat buffers reference the same file"""
175 return s1.st_ino == s2.st_ino and \
176 s1.st_dev == s2.st_dev
177
178
179
180
181
183 """Test whether a path is a mount point"""
184 if islink(path):
185
186 return False
187 try:
188 s1 = os.lstat(path)
189 s2 = os.lstat(realpath(join(path, '..')))
190 except os.error:
191 return False
192 dev1 = s1.st_dev
193 dev2 = s2.st_dev
194 if dev1 != dev2:
195 return True
196 ino1 = s1.st_ino
197 ino2 = s2.st_ino
198 if ino1 == ino2:
199 return True
200 return False
201
202
203
204
205
206
207
208
209
210
211 -def walk(top, func, arg):
212 """Directory tree walk with callback function.
213
214 For each directory in the directory tree rooted at top (including top
215 itself, but excluding '.' and '..'), call func(arg, dirname, fnames).
216 dirname is the name of the directory, and fnames a list of the names of
217 the files and subdirectories in dirname (excluding '.' and '..'). func
218 may modify the fnames list in-place (e.g. via del or slice assignment),
219 and walk will only recurse into the subdirectories whose names remain in
220 fnames; this can be used to implement a filter, or to impose a specific
221 order of visiting. No semantics are defined for, or required of, arg,
222 beyond that arg is always passed to func. It can be used, e.g., to pass
223 a filename pattern, or a mutable object designed to accumulate
224 statistics. Passing None for arg is common."""
225 warnings.warnpy3k("In 3.x, os.path.walk is removed in favor of os.walk.",
226 stacklevel=2)
227 try:
228 names = os.listdir(top)
229 except os.error:
230 return
231 func(arg, top, names)
232 for name in names:
233 name = join(top, name)
234 try:
235 st = os.lstat(name)
236 except os.error:
237 continue
238 if stat.S_ISDIR(st.st_mode):
239 walk(name, func, arg)
240
241
242
243
244
245
246
247
248
249
250
252 """Expand ~ and ~user constructions. If user or $HOME is unknown,
253 do nothing."""
254 if not path.startswith('~'):
255 return path
256 i = path.find('/', 1)
257 if i < 0:
258 i = len(path)
259 if i == 1:
260 if 'HOME' not in os.environ:
261 import pwd
262 userhome = pwd.getpwuid(os.getuid()).pw_dir
263 else:
264 userhome = os.environ['HOME']
265 else:
266 import pwd
267 try:
268 pwent = pwd.getpwnam(path[1:i])
269 except KeyError:
270 return path
271 userhome = pwent.pw_dir
272 userhome = userhome.rstrip('/')
273 return (userhome + path[i:]) or '/'
274
275
276
277
278
279
280 _varprog = None
281 _uvarprog = None
282
323
324
325
326
327
328
330 """Normalize path, eliminating double slashes, etc."""
331
332 slash, dot = (u'/', u'.') if isinstance(path, _unicode) else ('/', '.')
333 if path == '':
334 return dot
335 initial_slashes = path.startswith('/')
336
337
338 if (initial_slashes and
339 path.startswith('//') and not path.startswith('///')):
340 initial_slashes = 2
341 comps = path.split('/')
342 new_comps = []
343 for comp in comps:
344 if comp in ('', '.'):
345 continue
346 if (comp != '..' or (not initial_slashes and not new_comps) or
347 (new_comps and new_comps[-1] == '..')):
348 new_comps.append(comp)
349 elif new_comps:
350 new_comps.pop()
351 comps = new_comps
352 path = slash.join(comps)
353 if initial_slashes:
354 path = slash*initial_slashes + path
355 return path or dot
356
357
359 """Return an absolute path."""
360 if not isabs(path):
361 if isinstance(path, _unicode):
362 cwd = os.getcwdu()
363 else:
364 cwd = os.getcwd()
365 path = join(cwd, path)
366 return normpath(path)
367
368
369
370
371
373 """Return the canonical path of the specified filename, eliminating any
374 symbolic links encountered in the path."""
375 path, ok = _joinrealpath('', filename, {})
376 return abspath(path)
377
378
379
381 if isabs(rest):
382 rest = rest[1:]
383 path = sep
384
385 while rest:
386 name, _, rest = rest.partition(sep)
387 if not name or name == curdir:
388
389 continue
390 if name == pardir:
391
392 if path:
393 path, name = split(path)
394 if name == pardir:
395 path = join(path, pardir, pardir)
396 else:
397 path = pardir
398 continue
399 newpath = join(path, name)
400 if not islink(newpath):
401 path = newpath
402 continue
403
404 if newpath in seen:
405
406 path = seen[newpath]
407 if path is not None:
408
409 continue
410
411
412 return join(newpath, rest), False
413 seen[newpath] = None
414 path, ok = _joinrealpath(path, os.readlink(newpath), seen)
415 if not ok:
416 return join(path, rest), False
417 seen[newpath] = path
418
419 return path, True
420
421
422 supports_unicode_filenames = (sys.platform == 'darwin')
423
425 """Return a relative version of a path"""
426
427 if not path:
428 raise ValueError("no path specified")
429
430 start_list = [x for x in abspath(start).split(sep) if x]
431 path_list = [x for x in abspath(path).split(sep) if x]
432
433
434 i = len(commonprefix([start_list, path_list]))
435
436 rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
437 if not rel_list:
438 return curdir
439 return join(*rel_list)
440