Permalink
Cannot retrieve contributors at this time
Fetching contributors…
| #!/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='') |