使用Python os模块获取unix文件类型

时间:2017-06-16 18:24:14

标签: python unix operating-system

我想得到路径指定的文件的unix文件类型(找出它是普通文件,命名管道,块设备,......)

我在文档input中找到了,但在Python 3.6中,这似乎不起作用。

另一种方法是使用<div> <label for="???">Name</label> <input [(ngModel)]="name" type="text" id="???"/> </div> 个对象(例如os.stat(path).st_type),但只有方法os.DirEntryos.listdir(path)is_dir()

任何想法怎么做?

3 个答案:

答案 0 :(得分:2)

您使用stat模块来解释os.stat(path).st_mode的结果。

>>> import os
>>> import stat
>>> stat.S_ISDIR(os.stat('/dev/null').st_mode)
False
>>> stat.S_ISCHR(os.stat('/dev/null').st_mode)
True

您可以创建一般函数来返回确定的类型。这适用于Python 2和3。

import enum
import os
import stat

class PathType(enum.Enum):
    dir = 0  # directory
    chr = 1  # character special device file
    blk = 2  # block special device file
    reg = 3  # regular file
    fifo = 4  # FIFO (named pipe)
    lnk = 5  # symbolic link
    sock = 6  # socket
    door = 7  # door  (Py 3.4+)
    port = 8  # event port  (Py 3.4+)
    wht = 9  # whiteout (Py 3.4+)

    unknown = 10

    @classmethod
    def get(cls, path):
        if not isinstance(path, int):
            path = os.stat(path).st_mode
        for path_type in cls:
            method = getattr(stat, 'S_IS' + path_type.name.upper())
            if method and method(path):
                return path_type
        return cls.unknown

PathType.__new__ = (lambda cls, path: cls.get(path))
            
>>> PathType('/dev/null')
<PathType.chr: 1>
>>> PathType('/home')
<PathType.dir: 0>

答案 1 :(得分:1)

Python 3.6有pathlib,其Path个对象有方法:

  • is_dir()
  • is_file()
  • is_symlink()
  • is_socket()
  • is_fifo()
  • is_block_device()
  • is_char_device()

pathlib需要一点时间来习惯(至少对我来说是从Unix上的C / C ++来到Python),但它是一个很好的库

答案 2 :(得分:0)

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,因此无论是否存在错误。

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”提供的代码有效得多,这在处理大量文件时很重要。 python23的用法:

>>> 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'
>>>