#!/bin/python3 import argparse import datetime import glob import json import os import time installed=False while not installed: try: from terminaltables import DoubleTable from terminaltables import GithubFlavoredMarkdownTable installed=True except: print("Installing terminaltables") os.system("sudo pip3 install terminaltables") def uTd(ts): return datetime.datetime.utcfromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S') def get_size(start_path = '.'): total_size = 0 for dirpath, dirnames, filenames in os.walk(start_path): for f in filenames: fp = os.path.join(dirpath, f) # skip if it is symbolic link if not os.path.islink(fp): total_size += os.path.getsize(fp) return total_size def oneTrueNoMore(list): flag = False for element in list: if element: if flag: return False flag = True return True def getTab(data, args): if not oneTrueNoMore([ args.by_size_descending, args.by_size_ascending, args.by_adate_descending, args.by_adate_ascending, args.by_cdate_descending, args.by_cdate_ascending, args.by_mdate_descending, args.by_mdate_ascending, args.by_name_descending, args.by_name_ascending, ]): print("You must specify only ONE sorting mode") exit(1) if args.by_size_descending: data.sort(key=lambda el: el["size"]["size"]) data.reverse() elif args.by_size_ascending: data.sort(key=lambda el: el["size"]["size"]) elif args.by_adate_descending: data.sort(key=lambda el: el["dates"]["atime"]) data.reverse() elif args.by_adate_ascending: data.sort(key=lambda el: el["dates"]["atime"]) elif args.by_cdate_descending: data.sort(key=lambda el: el["dates"]["ctime"]) data.reverse() elif args.by_cdate_ascending: data.sort(key=lambda el: el["dates"]["ctime"]) elif args.by_mdate_descending: data.sort(key=lambda el: el["dates"]["mtime"]) data.reverse() elif args.by_mdate_ascending: data.sort(key=lambda el: el["dates"]["mtime"]) elif args.by_name_descending: data.sort(key=lambda el: el["name"]) data.reverse() elif args.by_name_ascending: data.sort(key=lambda el: el["name"]) if args.group: data.sort(key=lambda el: el["group"]) tab = [["Type", "Name", "Size", "Permissions", "Dates"]] for r in data: tab.append([r["desc"], r["name"], r["size"]["human"], r["permissions"], r["dates"]["humanAll"]]) return tab def sizeof_fmt(num, suffix='B'): for unit in ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']: if abs(num) < 1024.0: return "%3.1f%s%s" % (num, unit, suffix) num /= 1024.0 return "%.1f%s%s" % (num, 'Yi', suffix) data=[] parser = argparse.ArgumentParser(description='Improved ls') parser.add_argument('DIRECTORY', metavar='dir', type=str, help='DIRECTORY') parser.add_argument('--by-size-descending', "-sd", action='store_true', help='Sort by descending size') parser.add_argument('--by-size-ascending', "-sa", action='store_true', help='Sort by ascending size') parser.add_argument('--by-adate-descending', "-ldd", action='store_true', help='Sort by descending access date') parser.add_argument('--by-adate-ascending', "-lda", action='store_true', help='Sort by ascending access date') parser.add_argument('--by-cdate-descending', "-cdd", action='store_true', help='Sort by descending creation date') parser.add_argument('--by-cdate-ascending', "-cda", action='store_true', help='Sort by ascending creation date') parser.add_argument('--by-mdate-descending', "-mdd", action='store_true', help='Sort by descending edit date') parser.add_argument('--by-mdate-ascending', "-mda", action='store_true', help='Sort by ascending edit date') parser.add_argument('--by-name-descending', "-nd", action='store_true', help='Sort by descending name') parser.add_argument('--by-name-ascending', "-na", action='store_true', help='Sort by ascending name (Default)') parser.add_argument('--group', "-g", action='store_true', help='Group by type (directories, files, symlinks)') parser.add_argument('--markdown', "-md", action='store_true', help='Print markdown table') parser.add_argument('--show-author-info', "-a", action='store_true', help='Show author information about the directory (folders created with Imkdir)') args = parser.parse_args() if not os.path.isdir(args.DIRECTORY): print("Directory \""+args.DIRECTORY+"\" does not exist") exit(1) if not os.access(args.DIRECTORY, os.R_OK): print("Cannot access \"" + args.DIRECTORY + "\"") exit(1) k = glob.glob(args.DIRECTORY + "/*") for element in k: if os.path.islink(element): typ = "Symlink" name = os.path.basename(element) group = typ elif os.path.isdir(element): group = "Directory" descriptorArray = [] dirs = len([name for name in os.listdir(element) if os.path.isdir(os.path.join(element, name))]) if dirs > 0: if dirs == 1: descMeasure = "directory" else: descMeasure = "directories" descriptorArray.append(str(dirs) + " " + descMeasure) files = len([name for name in os.listdir(element) if os.path.isfile(os.path.join(element, name))]) if files > 0: if files == 1: descMeasure = "file" else: descMeasure = "files" descriptorArray.append(str(files) + " " + str(descMeasure)) symlinks = len([name for name in os.listdir(element) if os.path.islink(os.path.join(element, name))]) if symlinks > 0: if symlinks == 1: descMeasure = "symlink" else: symlinks = "symlinks" descriptorArray.append(str(symlinks) + " " + str(descMeasure)) typ = "Directory" if len(descriptorArray): typ += "\n (" + ", ".join(descriptorArray) + ")" name = os.path.basename(element) else: typ = "File" name = os.path.basename(element) rr = name.split(".") ext = "" if len(rr) > 1: ext = rr[len(rr) - 1].upper() typ += " " + ext group = typ stats = os.stat(element) size = sizeof_fmt(stats.st_size) dates = "Opened: " + uTd(stats.st_atime) + "\nEdited: " + uTd(stats.st_mtime) + "\nCreated: " + uTd(stats.st_ctime) mask = oct(stats.st_mode)[-3:] dT={ "desc": typ, "name": name, "size": { "human": size, "size": stats.st_size } , "permissions": mask, "dates": { "atime": stats.st_atime, "mtime": stats.st_mtime, "ctime": stats.st_ctime, "humanAll": dates} , "group": group } if dT["group"]== "Directory": dT["size"]["size"]=get_size(element) dT["size"]["human"]=sizeof_fmt(dT["size"]["size"]) data.append(dT) tableA = getTab(data, args) if args.markdown: table = GithubFlavoredMarkdownTable(tableA) else: table = DoubleTable(tableA) table.inner_row_border = True print("\n"+args.DIRECTORY + "\n\n+---------+\n") tabAuthor = [] columnsAuthor = { "name": "Name", "surname": "Suraname", "email": "Email", "gpg": "GPG Key", "gh": "Github", "te": "Telegram", "tw": "Twitter", "notes": "Notes", "created": "Created", "utcoffset": "Timezone", "platform": "Platform" } if args.show_author_info and os.path.isfile(args.DIRECTORY + "/.ilft"): data = json.loads(open(args.DIRECTORY + "/.ilft", "r").read()) for key in data.keys(): k=key if not data[key]: continue if k in columnsAuthor.keys(): k=columnsAuthor[k] if key=="created": data[key]=uTd(data[key]) elif key=="utcoffset": ts=int(data[key]) taa=abs(ts) data[key] = time.strftime('%Hh %Mm', time.gmtime(taa)) if ts<0: data[key]="-"+data[key] else: data[key]="+"+data[key] tabAuthor.append([k,data[key]]) if args.markdown: tabAuthor.insert(0,["Characteristic","Value"]) TA = GithubFlavoredMarkdownTable(tabAuthor) else: TA = DoubleTable(tabAuthor) TA.inner_heading_row_border=False print(TA.table+"\n\n") print(table.table)