-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathconvert-ts-bash-history.py
More file actions
executable file
·71 lines (60 loc) · 2.38 KB
/
convert-ts-bash-history.py
File metadata and controls
executable file
·71 lines (60 loc) · 2.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#!/usr/bin/env python3
"""
Author: Jim Clausing <jclausing@isc.sans.edu>
Date: 2026-03-17
Version: 1.0.0
This script takes 1 or more filenames of .bash_history files
and returns a | separated list with
<filename>|<datetime>|<command>
where <datetime> is ISO-8601 date and time if timestamps were
recorded in the history file and NA, if not
usage: convert-ts-bash-history.py file [file ...]
"""
__description__ = ('Program to convert .bash_history files to | separated list with ISO-8601 timestamps')
__author__ = 'Jim Clausing'
__version__ = '1.0.0'
__date__ = '2026-03-17'
import argparse
import sys
import re
import os
from datetime import datetime
def parse_bash_history(filename):
with open(filename, 'r', encoding='utf-8', errors='replace') as f:
lines = f.readlines()
results = []
timestamp = None
time_regex = re.compile(r'^#(\d+)$')
for line in lines:
line = line.rstrip('\n')
match = time_regex.match(line)
if match:
timestamp = int(match.group(1))
else:
if timestamp is not None:
iso_time = datetime.fromtimestamp(timestamp).isoformat()
if args.nofilename:
results.append(f"{iso_time}|{line}")
else:
results.append(f"{filename}|{iso_time}|{line}")
timestamp = None
else:
if args.nofilename:
results.append(f"NA|{line}")
else:
results.append(f"{filename}|NA|{line}")
return results
if __name__ == '__main__':
parser = argparse.ArgumentParser(usage=' ' + os.path.basename(__file__) + ' FILENAME [FILENAME ...]\n' + __description__)
parser.add_argument('filenames', metavar='FILENAME', nargs='+',
help='path to .bash_history file(s) to convert')
parser.add_argument('-f', '--nofilename', action="store_true", help='suppress filename output')
parser.add_argument('-V', '--version', action='version', help='print version number',
version='%(prog)s v' + __version__)
args = parser.parse_args()
for filename in args.filenames:
try:
for entry in parse_bash_history(filename):
print(entry)
except (FileNotFoundError, PermissionError) as e:
print(f"Error: {e}", file=sys.stderr)