Open baodrate opened 1 year ago
my solution uses sed and .import:
#!/bin/sh
LC_CTYPE=C sed -e ':a;/\\$/{N;b a};s/"/""/g;t b;:b;s/^: \([0-9]*\):\([0-9]*\);\(.*\)$/"\3",\1,\2/;t;s/.*/"&","",""/' ~/.zsh_history | sqlite3 3<&0 << EOF
CREATE TABLE zsh_history(argv text, started int, duration int);
.import --csv /dev/fd/3 zsh_history
ATTACH DATABASE '$HOME/.histdb/zsh-history.db' AS histdb;
BEGIN;
INSERT INTO histdb.commands (argv) SELECT argv FROM zsh_history ORDER BY rowid;
INSERT INTO histdb.history (command_id, start_time, duration) SELECT rowid, started, duration FROM zsh_history ORDER BY rowid;
COMMIT;
EOF
it takes a couple seconds to import 150k lines. I don't think this handles duration etc correctly though, and I don't think histdb is right for me so I probably won't improve this.
In case this helps anyone else, here's a function to parse zsh's histfile and add it to the database. Leverages zsh's history file parsing so it handles newlines and arbitrary characters very well. The other tools suggested in the README require other languages and don't handle multiline commands soundly.
Inserts are batched and it's pretty fast. A bit of time is wasted calling
fc -l
to read the timestamps, but it takes ~1s to parse ~20k lines for me so it should be fast enough for most use-cases.Note that:
session
to0
(sqlite starts its autoincrement ids at 1so it shouldn't coincide with any histdb sessionszsh-histdb actually initializes session to 0 if none currently exist, so a different value might be desirable (-1?))dir
is set to the empty string (''
) instead ofNULL
because sqlite doesn't let you useNULL
as part of a keyunique(session, command_id, place_id, start_time) on conflict ignore
constraint to thehistory
table so history instances are de-duped. Useful if you have a bunch of history file backups to import.on conflict ... do update ... where ...
clause