2020年11月20日
'Artyer'提供的代码在python 2.7.17
中无法运行,但似乎在python 3.6.9
中可以工作,除了一个细节:
调用:
path = os.stat(path).st_mode
应该是:
path = os.lstat(path).st_mode
否则,您只会得到软链接指向的常规文件。
对于Python 2(和3),如果您希望遵循这种编码风格,则以下代码更好,为了清晰起见进行了一些名称更改:
import enum,os,stat
class PathTypes(enum.Enum):
door = 0
port = 1
wht = 2
dir = 3
chr = 4
blk = 5
reg = 6
fifo = 7
lnk = 8
sock = 9
unimplemented = 10
def filetype(path):
mode=os.lstat(path).st_mode
for t in PathTypes:
try: func=getattr(stat, 'S_IS' + t.name.upper())
except AttributeError: continue
if func(mode): return t
return PathTypes["unimplemented"]
注意重新排序,强制在
python 2
中考虑未定义的stat函数并练习必要的
try ... except
语句。成员也被重新编号,因为在
python 2
中,
enum.ENUM
显然按值对成员进行排序,而这显然没有记录。由于现在不支持
python 2
,无论是否有错误,都是这样。
enum
文档建议不要使用值
0
,因为它是布尔值
False
,所有成员都应该是布尔值
True
。文档还建议使用这种更简单的帮助程序样式。
(
https://cpython-test-docs.readthedocs.io/en/latest/library/enum.html)
为了避免一些歧义,以下内容将按照文档说明操作,并按顺序处理以快速返回最可能的结果。
import enum,os,stat
members= ( \
('reg', 'S_ISREG' ), \
('dir', 'S_ISDIR' ), \
('lnk', 'S_ISLNK' ), \
('fifo', 'S_ISFIFO'), \
('sock', 'S_ISSOCK'), \
('chr', 'S_ISCHR' ), \
('blk', 'S_ISBLK' ), \
('door', 'S_ISDOOR'), \
('port', 'S_ISPORT'), \
('wht', 'S_ISWHT' ), \
('unimplemented', '') \
)
FileTypes=enum.Enum('FileTypes',members)
def filetype(path):
"""Get unix filetype:
reg,dir,lnk,fifo,sock,chr,blk
and for py3.4+:
door,port,wht.
'path' is a full pathname for some file."""
mode=os.lstat(path).st_mode
for t in FileTypes:
try: func=getattr(stat, t.value)
except AttributeError: continue
if func(mode): return t
return FileTypes["unimplemented"]
enum.ENUM
函数 API 显然没有排序错误,并按照文档中呈现的顺序保留成员。
考虑到 enum.ENUM
的麻烦性质,最好还是通过使用经过时间测试的 python
原语来避免它:
import os,stat
_stat_funcs=( \\
'S_ISREG','S_ISDIR','S_ISLNK','S_ISFIFO','S_ISSOCK', \\
'S_ISCHR','S_ISBLK','S_ISDOOR','S_ISPORT','S_ISWHT' )
_ls_chr=( \\
'-' ,'d' ,'l' ,'p' ,'s' , \\
'c' ,'b' ,'D' ,'P' ,'w' )
_ftypes=tuple( (c,getattr(stat,f)) \\
for c,f in zip(_ls_chr,_stat_funcs) if f in dir(stat))
def filetype(path):
"""Get unix filetype designator used in 'ls' shell command listings:
reg('-'),dir('d'),lnk('l'),fifo('p'),sock('s'),chr('c'),blk('b')
and for py3.4+:
door('D'),port('P'),wht('w'). (solaris,solaris,BSD only)
'path' is a full pathname for some file. Returns 'u' for an
unknown or unimplemented filetype."""
mode=os.lstat(path).st_mode
for c,func in _ftypes:
if func(mode): return c
return 'u'
这比代码 'Artyer' 提供的要高效得多,当处理大量文件时非常重要。对于 python2
和 3
的用法:
>>> filetype('/dev/null')
'c'
>>> filetype('/dev/sda')
'b'
>>> filetype('/home/test')
'd'
>>> filetype('/home/random.txt')
'-'
>>> filetype('/home/test/hlnk')
'-'
>>> filetype('/home/test/slnk')
'l'
>>> filetype('/home/test/sckt')
's'
>>> filetype('/home/test/fifo.pipe')
'p'
>>>
ruamel.std.pathlib
,它对Path
进行了一些扩展,并提供了一个“PathLibConversionHelper”类来帮助过渡。 - Anthon