123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- #!/usr/bin/python3
- # Bash History Analyser
- # by Farooq Karimi Zadeh
- # fkz@riseup.net
- # Under GNU GPLv3+
- # This software is free software and COMES WITHOUT ANY WARRENTY FROM MAIN AUTHOR
- # https://notabug.org/farooqkz/BHA
- import sys
- import os
- def fexist(path): # file exist
- return os.path.isfile(path)
- def cexist(command): # command exist
- for path in os.environ["PATH"].split(":"):
- if fexist(f"{path}/{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='')
|