Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
124 lines (99 sloc) 3.32 KB
#!/usr/bin/python3
# Bash History Analyser
# by Farooq Karimi Zadeh
# farooghkarimizadeh@gmail.com
# Under GNU GPLv3+
# This software is free software and COMES WITHOUT ANY WARRENTY FROM MAIN AUTHOR
# https://github.com/farooqkz/bha
import sys
import os
def fexist(path): # file exist
try:
fs = open(path)
except:
return 0
else:
return 1
def cexist(command): # command exist
if fexist('/bin/' + command) or fexist('/sbin/' + command): return True
if fexist('/usr/bin/' + command) or fexist('/usr/games/' + command): return True
if fexist('/usr/sbin/' + command): return True
if fexist('/usr/local/bin/' + command): return True
if fexist('/usr/local/games/' + command): return True
return False
def usage():
print('Usage: bha [History_file_path]')
def dictsort(adict): # this function sorts a map by its values (uses bubblesort)
keys = list(adict.keys())
values = list(adict.values())
swaped = 1
while swaped:
swaped = 0
for i in range(len(values)):
if i == len(values) - 1: continue
if values[i] < values[i+1]:
values[i], values[i+1] = values[i+1], values[i]
keys[i], keys[i+1] = keys[i+1], keys[i] # swap
swaped = 1
return [keys, values]
def excmd(s): # EXtracts CoMMands from a given string
# first we delete anything between two "
ns = '' # new string
inq = False
for i in s:
if i == '\"':
inq = not inq # toggle
continue
if not inq:
ns += i
# then we delete anything between two '
fs = '' # final string
inq = False
for i in ns:
if i == '\'':
inq = not inq
continue
if not inq:
fs += i
cmds = []
for i in fs.split(' '):
if i.startswith('./'): # we don't count them
continue
if i.startswith('#'): # we don't count comments
continue
if i == 'sudo' or i == 'su': # they aren't command.are they?
continue
if cexist(i):
cmds.extend([i])
return cmds
history_file_path = os.path.expanduser('~') + '/.bash_history'
if len(sys.argv) == 2: history_file_path = sys.argv[1]
fs = open(history_file_path) # opens a File Stream for text reading
history = fs.read() # reads all what is in file
fs.close() # closes the file stream (no longer we need it)
history = history.split('\n') # => a list of strings seprated by a new line
cmds = {} # an empty map
for i in history:
for cmd in excmd(i):
if cmd not in cmds:
cmds[cmd] = 1
else:
cmds[cmd] += 1
cmds = dictsort(cmds) # {'ls': 125, 'gcc': 10, 'cat': 100} => [['ls', 'cat', 'gcc'], [125, 100, 10]]
total = sum(cmds[1]) # [0, 1, 2] => 3
othercc = 0 # Other Commands Count (anything lower than 0.25%)
otherc = [] # list of other commands
for i in range(len(cmds[0])):
cmd = cmds[0][i]
count = cmds[1][i]
percent = count / total * 100
if percent < 0.25:
othercc += count
otherc.extend([cmd])
else:
print(cmd + ': ', round(percent,2), '%', ' (', count, '/', total, ')', sep='')
print('other commands: ')
for i in otherc:
print(i, end=', ')
print()
print('% of other: ', round(othercc/total*100, 2), '%', ' (', othercc, '/', total, ')', sep='')