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 # door (Py 3.4+)
port = 1 # event port (Py 3.4+)
wht = 2 # whiteout (Py 3.4+)
dir = 3 # directory
chr = 4 # character special device file
blk = 5 # block special device file
reg = 6 # regular file
fifo = 7 # FIFO (named pipe)
lnk = 8 # symbolic link
sock = 9 # socket
unimplemented = 10
def filetype(path):
mode=os.lstat(path).st_mode # do not follow links
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 中的测试考虑未定义的统计函数并执行必要的try...except 语句。成员也被重新编号,因为在python 2、enum.ENUM 中显然是按值对成员进行排序,这显然是无证的。由于现在不支持python 2,不管有没有bug,就是这样。
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 # do not follow links
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' )
# ^----- python 3.4+ only ----->|
# ^-- SOLARIS only --->|^--BSD->|
_ls_chr=( \\
'-' ,'d' ,'l' ,'p' ,'s' , \\
'c' ,'b' ,'D' ,'P' ,'w' )
# ^----- python 3.4+ only------>|
# ^-- SOLARIS only --->|^--BSD->|
_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 # do not follow links
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') # hard link
'-'
>>> filetype('/home/test/slnk') # soft link
'l'
>>> filetype('/home/test/sckt')
's'
>>> filetype('/home/test/fifo.pipe')
'p'
>>>