Loading... ``` # coding: utf8 import argparse import os import time from pathlib import Path from sys import (stdout, stderr) from functools import wraps def catch(func): @wraps(func) def _catch(*args, **kwargs): try: result = func(*args, **kwargs) except Exception as err: stderr.write(str(err) + '\n') exit(3) else: return result return _catch def get_args(): """ 获取命令行参数 :return: args object """ parser = argparse.ArgumentParser(add_help=False) parser.add_argument('-h', dest='human', help='使文件大小易读', action='store_true') parser.add_argument('-l', '--list', help='显示详细信息', action='store_true') parser.add_argument('-a', '--all', help='显示隐藏文件', action='store_true') parser.add_argument('path', nargs='*', default='.', type=str, help='文件或者目录路径,默认是当前目录') # 默认路径,路径可以指定多个 # parser.add_argument('args', nargs=argparse.REMAINDER) # 将剩余选选项聚集到一个列表, 这个列表将被抛弃。都是无用参数 parser.add_argument('--help', action='help') # 帮助 return parser.parse_args() def file_size(src): """ 文件大小转换为易读数值 :param src: int 原始值 :return: bytes """ def _tran(number, typ): return '{}{}'.format(number, typ).encode() if src < 1024: return str(src).encode() if round(src / (1024 ** 3), 1) < 1024: if round(src / 1024, 1) < 1024: return _tran(round(src / 1024, 1), 'K') elif round(src / 1024 ** 2, 1) < 1024: return _tran(round(src / (1024 ** 2), 1), 'M') else: return _tran(round(src / (1024 ** 3), 1), 'G') else: if round(src / (1024 ** 4), 1) < 1024: return _tran(round(src / (1024 ** 4), 1), 'T') else: return _tran(round(src / (1024 ** 5), 1), 'P') def file_type(path_obj): if path_obj.is_file(): return b'-' if path_obj.is_dir(): return b'd' if path_obj.is_char_device(): return b'c' if path_obj.is_fifo(): return b'p' if path_obj.is_block_device(): return b'b' if path_obj.is_socket(): return b's' if path_obj.is_symlink(): return b'l' def get_time(timestamp): return time.strftime("%Y-%m-%d %H:%M", time.localtime(timestamp)).encode() def purview(n): """ 权限数字转换为字符 :param n: st_mode :return: bytes """ _purview = n & 0o777 _string = bytearray() # 获取权限 def _transform(number): """ 数字转换为权限 rwx :param number: 十进制数据 0-7 :return: bytes """ index = 2 result = bytearray() for s in b'rwx': result.append(s if (number >> index & 1) else 0x2D) index -= 1 return result def _transform1(number): """ 数字转换为权限 rwx 效率稍微高于 _transform :param number: 十进制数据 0-7 :return: bytes """ string = b'rxw' return bytearray(string[_ - 2] if (number >> _ & 1) else 0x2D for _ in range(2, -1, -1)) for i in range(6, -1, -3): if i == 6: tmp = _purview >> i else: tmp = _purview >> i & 0o7 _string.extend(_transform1(tmp)) return _string def get_user(uid): """ 获取用户名 :param uid: uid :return: username """ uid = str(uid) name_file = '/etc/passwd' if os.name == 'posix' and Path(name_file).exists(): with open(name_file, encoding='utf8') as file: for line in file.readlines(): if uid in line: return line.split(':')[0] return uid def get_group(gid): """ 获取用户组 :param gid: gid :return: group name """ gid = str(gid) group_file = '/etc/group' if os.name == 'posix' and Path(group_file).exists(): with open(group_file, encoding='utf8') as file: for line in file.readlines(): if gid in line: return line.split(':')[0] return gid def detailed(path_obj, size=False): """ 详细显示文件信息 :param path_obj: 路径对象 :param size: 是否使文件大小易读 :return: string """ stat = path_obj.stat() string = [ (file_type(path_obj) + purview(stat.st_mode)).decode(), # 文件类型和权限 str(stat.st_nlink), # 硬链接 get_user(stat.st_uid), # uid or user name get_group(stat.st_gid), # gid or group name file_size(stat.st_size).decode() if size else str(stat.st_size), # 文件大小 get_time(stat.st_ctime).decode(), # 创建时间 path_obj.name if path_obj.name else '.' # 文件名 ] return '\t'.join(string) + '\n' @catch def main(): args = get_args() code = 0 flag = False for path in args.path: path_obj = Path(path) if not path_obj.exists(): # 如果文件不存在 stderr.write('{}: No Such File Or Directory.'.format(path) + '\n') code = 2 continue if path_obj.is_dir(): # 如果是个文件夹 files_list = ['.', '..'] if flag: # 如果之前有文件出现过 stdout.write('\n{}:\n'.format(path_obj.name)) files_list += [i.name for i in path_obj.iterdir()] files_list.sort(key=str) if not args.all: # 不要显示隐藏文件 files_list = [i for i in files_list if i[0] != '.'] if args.list: # 如果显示了详细信息 for file in files_list: _path_obj = path_obj / file # 文件path对象 stdout.write(detailed(_path_obj, args.human)) else: stdout.write('\t'.join(files_list) + '\n') else: # 如果不是一个目录 flag = True if args.list: # 如果需要显示详细信息 stdout.write(detailed(path_obj, size=args.human)) continue stdout.write(path_obj.name) stdout.write('\t') if flag: stdout.write('\n') return code if __name__ == '__main__': exit(main()) ``` 最后修改:2020 年 09 月 07 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 0 如果觉得我的文章对你有用,请随意赞赏
2 条评论
内容的丰富性和深度让人仿佛置身于知识的海洋,受益匪浅。
意象选取精妙,营造出空灵意境。