Add files via upload
This commit is contained in:
parent
f219ad1e40
commit
9f099f3941
241
Ils
Normal file
241
Ils
Normal file
|
@ -0,0 +1,241 @@
|
||||||
|
#!/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)
|
66
Imkdir
Normal file
66
Imkdir
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
#! /bin/python3
|
||||||
|
import argparse,shlex,os,subprocess,json,time,platform,datetime
|
||||||
|
def mkdir(cmd,dirs,data):
|
||||||
|
try:
|
||||||
|
subprocess.check_output(cmd, shell=True, text=True)
|
||||||
|
for d in dirs:
|
||||||
|
open(d+"/.ilft","w").write(json.dumps(data))
|
||||||
|
except Exception as e:
|
||||||
|
return False
|
||||||
|
config_folder=os.path.expanduser("~")+"/.config/ilftools/"
|
||||||
|
parser = argparse.ArgumentParser(description='Improved mkdir')
|
||||||
|
parser.add_argument('DIRECTORIES', metavar='dir', type=str, nargs='+',help='DIRECTORY(ies)')
|
||||||
|
parser.add_argument('--version', action='version', version='%(prog)s 0.1')
|
||||||
|
parser.add_argument('--mode', "-m", metavar='mode', type=str, help=' set file mode (as in chmod), not a=rwx - umask')
|
||||||
|
parser.add_argument('--parents',"-p",action='store_true',help='no error if existing, make parent directories as needed')
|
||||||
|
parser.add_argument('--verbose',"-v",action='store_true',help='print a message for each created directory')
|
||||||
|
parser.add_argument('-Z',action='store_true',help='set SELinux security context of each created directory to the default type')
|
||||||
|
parser.add_argument('--context', metavar='context', type=str,help='like -Z, or if CTX is specified then set the SELinux or SMACK security context to CTX')
|
||||||
|
parser.add_argument('--emulate',"-e", action='store_true',help='Emulate mkdir directly, no additional features')
|
||||||
|
parser.add_argument('--anonymous',"-a", action='store_true',help='Don\'t add personal info to the directories')
|
||||||
|
args = parser.parse_args()
|
||||||
|
cmd="mkdir "
|
||||||
|
if args.Z:
|
||||||
|
cmd+="-Z "
|
||||||
|
if args.mode != None :
|
||||||
|
cmd+="-m "+shlex.quote(args.mode)+" "
|
||||||
|
if args.context != None:
|
||||||
|
cmd+="--context "+shlex.quote(args.context)+" "
|
||||||
|
if args.parents:
|
||||||
|
cmd+="-p "
|
||||||
|
if args.verbose:
|
||||||
|
cmd+="-v "
|
||||||
|
for d in args.DIRECTORIES:
|
||||||
|
cmd+=shlex.quote(d)+" "
|
||||||
|
if not os.path.exists(config_folder+"author"):
|
||||||
|
r=str(input("No author info has been specified for this user.\nIt will be stored in /.config/ilftools/\nDo you want to set the data now? [y/N]? "))
|
||||||
|
rn=r.strip().lower()
|
||||||
|
if rn=="yes" or rn=="y":
|
||||||
|
print("--------\nCAUTION: this information will be added to any repository created by Imkdir\nIf you want to create a directory without personal data, try Imkdir -a\n--------")
|
||||||
|
name=str(input("Name: "))
|
||||||
|
surname=str(input("Surname: "))
|
||||||
|
nickname=str(input("Nickname: "))
|
||||||
|
email=str(input("Email: "))
|
||||||
|
gpg=str(input("GPG key: "))
|
||||||
|
gh=str(input("GitHub usename: "))
|
||||||
|
te=str(input("Telegram usename: "))
|
||||||
|
tw=str(input("Twitter usename: "))
|
||||||
|
notes=str(input("Notes:"))
|
||||||
|
data={"name":name,"surname":surname,"nickname":nickname,"email":email,"gpg":gpg,"gh":gh,"te":te,"tw":tw,"notes":notes}
|
||||||
|
dsj=json.dumps(data)
|
||||||
|
os.system("mkdir -p "+config_folder)
|
||||||
|
open(config_folder+"author","w").write(dsj)
|
||||||
|
dsj=data
|
||||||
|
print("--------\nConfiguration saved, proceeding to make the directory\n--------")
|
||||||
|
else:
|
||||||
|
dsj={}
|
||||||
|
else:
|
||||||
|
if not args.anonymous:
|
||||||
|
dsj=json.loads(open(config_folder+"author","r").read())
|
||||||
|
else:
|
||||||
|
dsj={}
|
||||||
|
|
||||||
|
dsj["created"]=datetime.datetime.utcnow().timestamp()
|
||||||
|
dsj["utcoffset"]=-time.timezone
|
||||||
|
dsj["platform"]=platform.system()
|
||||||
|
mkdir(cmd,args.DIRECTORIES,dsj)
|
99
README.md
Normal file
99
README.md
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
# ILFT - Interactive Linux File Tools
|
||||||
|
|
||||||
|
Collection of tools for interactive and metadata-friendly directory and file management
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
* **Ils**
|
||||||
|
|
||||||
|
*Interactive ls*
|
||||||
|
|
||||||
|
Ls, with pretty tables, dir overviews, permissions and much more
|
||||||
|
|
||||||
|
The author data is fetched from ``{DIR}/.ilft`` as saved by **Imkdir**
|
||||||
|
|
||||||
|
Example
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
![img](https://i.imgur.com/CbWOHxA.png)
|
||||||
|
|
||||||
|
![img](https://i.imgur.com/K7YO5YP.png)
|
||||||
|
|
||||||
|
```
|
||||||
|
usage: Ils [-h] [--by-size-descending] [--by-size-ascending] [--by-adate-descending]
|
||||||
|
[--by-adate-ascending] [--by-cdate-descending] [--by-cdate-ascending]
|
||||||
|
[--by-mdate-descending] [--by-mdate-ascending] [--by-name-descending]
|
||||||
|
[--by-name-ascending] [--group] [--markdown] [--show-author-info]
|
||||||
|
dir
|
||||||
|
|
||||||
|
Improved ls
|
||||||
|
|
||||||
|
positional arguments:
|
||||||
|
dir DIRECTORY
|
||||||
|
|
||||||
|
optional arguments:
|
||||||
|
-h, --help show this help message and exit
|
||||||
|
--by-size-descending, -sd
|
||||||
|
Sort by descending size
|
||||||
|
--by-size-ascending, -sa
|
||||||
|
Sort by ascending size
|
||||||
|
--by-adate-descending, -ldd
|
||||||
|
Sort by descending access date
|
||||||
|
--by-adate-ascending, -lda
|
||||||
|
Sort by ascending access date
|
||||||
|
--by-cdate-descending, -cdd
|
||||||
|
Sort by descending creation date
|
||||||
|
--by-cdate-ascending, -cda
|
||||||
|
Sort by ascending creation date
|
||||||
|
--by-mdate-descending, -mdd
|
||||||
|
Sort by descending edit date
|
||||||
|
--by-mdate-ascending, -mda
|
||||||
|
Sort by ascending edit date
|
||||||
|
--by-name-descending, -nd
|
||||||
|
Sort by descending name
|
||||||
|
--by-name-ascending, -na
|
||||||
|
Sort by ascending name (Default)
|
||||||
|
--group, -g Group by type (directories, files, symlinks)
|
||||||
|
--markdown, -md Print markdown table
|
||||||
|
--show-author-info, -a
|
||||||
|
Show author information about the directory (folders created with
|
||||||
|
Imkdir)
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
* **Ilmkdir**
|
||||||
|
|
||||||
|
*Interactive mkdir*
|
||||||
|
|
||||||
|
Mkdir with author data
|
||||||
|
|
||||||
|
On the first run, it saved personal information in ``~/.config/ilftools/author`` through a guided procedure
|
||||||
|
|
||||||
|
When a directory is created through this tool, data is saved in ``{DIR}/.ilft``
|
||||||
|
|
||||||
|
```
|
||||||
|
usage: Imkdir [-h] [--version] [--mode mode] [--parents] [--verbose] [-Z]
|
||||||
|
[--context context] [--emulate] [--anonymous]
|
||||||
|
dir [dir ...]
|
||||||
|
|
||||||
|
Improved mkdir
|
||||||
|
|
||||||
|
positional arguments:
|
||||||
|
dir DIRECTORY(ies)
|
||||||
|
|
||||||
|
optional arguments:
|
||||||
|
-h, --help show this help message and exit
|
||||||
|
--version show program's version number and exit
|
||||||
|
--mode mode, -m mode set file mode (as in chmod), not a=rwx - umask
|
||||||
|
--parents, -p no error if existing, make parent directories as needed
|
||||||
|
--verbose, -v print a message for each created directory
|
||||||
|
-Z set SELinux security context of each created directory to the
|
||||||
|
default type
|
||||||
|
--context context like -Z, or if CTX is specified then set the SELinux or SMACK
|
||||||
|
security context to CTX
|
||||||
|
--emulate, -e Emulate mkdir directly, no additional features
|
||||||
|
--anonymous, -a Don't add personal info to the directories
|
||||||
|
```
|
||||||
|
|
||||||
|
|
7
install.sh
Normal file
7
install.sh
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#!/bin/bash
|
||||||
|
echo "Installing..."
|
||||||
|
sudo chmod +x Ils
|
||||||
|
sudo cp Ils /bin/Ils
|
||||||
|
sudo chmod +x Imkdir
|
||||||
|
sudo cp Imkdir /bin/Imkdir
|
||||||
|
echo "Installed!"
|
Reference in New Issue
Block a user