ls命令的python不完全实现

  

from pathlib import Path
import argparse,sys,datetime,stat,platform

def showdir(path:str='.',all=False,detail=False,human=False,reverse=False):
    def convert_type_mode(file:Path)->str:
        return stat.filemode(file.stat().st_mode)

    def convert_mode(mode:int)->str: # 转换文件权限
        modelist=list('rwx'*3)
        modestr=bin(mode)[-9:]
        s=''
        for i,c in enumerate(modestr):
            if c == '1':
                s+=modelist[i]
            else:
                s+='-'
        return s

    # b=Path().stat().st_mode
    # def _getmodestr(mode:int)->str:
    #     modelist=list('rwx'*3)
    #     m=mode & 0o777
    #     print('mode',mode)
    #     print(m,oct(m),bin(m))
    #     s=''
    #     for i,v in enumerate(bin(m)[-9:]): # 将int转换为str进行迭代
    #         if v == '1':
    #             s+=modelist[i]
    #         else:
    #             s+='-'
    #     return s
    #
    # b = Path().stat().st_mode
    # def _getmodestr(mode: int) -> str: # 移位操作
    #     modelist = list('rwx' * 3)
    #     modedict = dict(zip(range(9), modelist))  # 倒序字典
    #     m = mode & 0b111111111
    #     s = ''
    #     for i in range(8, -1, -1):
    #         if m >> i & 1:
    #             s += modedict.get(8 - i)
    #         else:
    #             s += '-'
    #     return s

    def convert_type(file:Path)->str: # 转换文件类型
        s=''
        if file.is_symlink():
            s='l'
        elif file.is_dir():
            s='d'
        elif file.is_char_device():
            s='c'
        elif file.is_fifo():
            s='p'
        elif file.is_socket():
            s='s'
        elif file.is_block_device():
            s='b'
        else:
            s='-'
        return s

    def convert_time(f:float)->str: # 转换时间格式
        return datetime.datetime.fromtimestamp(f).strftime('%Y-%m-%d %H:%M:%S')

    def convert_human(size:int)->str: # 转换size为human_readable
        units=['']+list('KMGTPE')
        #units=' KMGTPE'
        depth=-1
        # while size >= 1000:
        #     size//=1000
        #     depth+=1
        # return '{}{}'.format(size,units[depth])

        def _human(size:int)->str:
            nonlocal depth
            depth+=1
            if size<1000:
                return '{}{}'.format(size,units[depth])
            return _human(size//1000)

        return '{:>5}'.format(_human(size))

    def _get_owner_group(file:Path): # 得到属主和属组
        if platform.system() == 'Linux':
            return '{} {}'.format(file.owner,file.group)
        else:
            return '{} {}'.format(file.stat().st_uid,file.stat().st_gid)

    def _showdir(path:str='.',all=False,detail=False,human=False):
        p=Path(path)
        # p.owner
        for file in p.iterdir():
            # yield file.name
            # todo -rw-r--r--. 1 root root 127 Nov 14 10:13 bb.py
            # todo Linux and Windows Path().stat()
            # os.stat_result(st_mode=33188, st_ino=33574979, st_dev=64768, st_nlink=1, st_uid=0, st_gid=0, st_size=33, st_atime=1573697346, st_mtime=1573697281, st_ctime=1573697281)
            # os.stat_result(st_mode=16895, st_ino=1407374883707564, st_dev=778327066, st_nlink=1, st_uid=0, st_gid=0, st_size=24576, st_atime=1600576373, st_mtime=1600531501, st_ctime=1535871988)
            # if not all:
            #     if file.name.startswith('.'):
            #         continue
            if not all and file.name.startswith('.'):
                continue
            if detail:
                st=file.stat()
                human_size=str(st.st_size)
                if human: # 在detail(-l)为True时,human(-h)才进行判断
                    human_size=convert_human(st.st_size)
                yield (convert_type(file)+convert_mode(st.st_mode),st.st_nlink,_get_owner_group(file),human_size,convert_time(st.st_atime),file.name)
            else:
                yield (file.name,)
    yield from sorted(_showdir(path,all,detail,human),key=lambda b:b[-1],reverse=reverse)

# 创建参数解析器实例
parser=argparse.ArgumentParser(prog='ls',add_help=False,description='i\'m a decscription')
parser.add_argument('-l','--list',action="store_true",help='list detail')
parser.add_argument('--all','-a',action="store_true",help='show all files')
parser.add_argument('-h',action='store_true',help='human readable size')
parser.add_argument('-r',action='store_true',help='reverse')
# 位置参数,可有可无,,缺省值'.'
parser.add_argument('path',nargs='?',default='.',help='input a directory')

if __name__ == '__main__':
    # args=parser.parse_args('c:/users/flirt\x20flare -lh'.rsplit(maxsplit=1)) # 分析参数,传入可迭代参数
    args=parser.parse_args()
    print('args=',args) # 打印namespace中收集的参数
    print('args.path={}\nargs.all={}\nargs.list={}\nargs.h={}\nargs.r={}'.format(args.path,args.all,args.list,args.h,args.r))
    parser.print_help()

    for st in showdir(args.path,all=args.all,detail=args.list,human=args.h,reverse=args.r):
        print(str(st).strip('()'))


# def listdir(path,all=False,detail=False):
#     """list detail of the path"""
#     p=Path(path)
#     for i in p.iterdir():
#         if not all and i.name.startswith('.'):
#             continue
#         if not detail:
#             yield (i.name)
#         else:
#             stat=i.stat()
#             mode=_getfiletype(i)+_getfilemode(stat.st_mode)
#             atime=datetime.datetime.fromtimestamp(stat.st_atime).strftime('%Y-%m-%d %H:%M:%S')
#             yield (mode,stat.st_nlink,stat.st_uid,stat.st_gid,stat.st_size,atime,i.name)
#
    yield from sorted(_listdir(path,all,detail,human),key=lambda x:x[len(x)-1])

if __name__ == '__main__':
    args=parser.parse_args()
    print(args)
    parser.print_help()
    files=listdir(args.path,args.all,args.l,args.human_readable)
    print(list(files))

  

 

上一篇:数据开发_Python读取CSV文件_csv库


下一篇:JDBC的编码步骤