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