package cmd import ( "context" "encoding/json" "fmt" "io" "os" "github.com/ddworken/hishtory/client/data" "github.com/ddworken/hishtory/client/hctx" "github.com/ddworken/hishtory/client/lib" "github.com/spf13/cobra" ) var exportJsonCmd = &cobra.Command{ Use: "export-json", Short: "Export history entries formatted in JSON lines format (as accepted by hishtory import-json, and easily parsable by other tools)", GroupID: GROUP_ID_MANAGEMENT, Run: func(cmd *cobra.Command, args []string) { ctx := hctx.MakeContext() err := exportToJson(ctx, os.Stdout) lib.CheckFatalError(err) }, } func structToMap(entry data.HistoryEntry) (map[string]interface{}, error) { inrec, err := json.Marshal(entry) if err != nil { return nil, err } var m map[string]interface{} err = json.Unmarshal(inrec, &m) return m, err } func exportToJson(ctx context.Context, w io.Writer) error { db := hctx.GetDb(ctx) chunkSize := 1000 offset := 0 for { entries, err := lib.SearchWithOffset(ctx, db, "", chunkSize, offset) if err != nil { return fmt.Errorf("failed to search for history entries with offset=%d: %w", offset, err) } if len(entries) == 0 { break } for _, entry := range entries { if entry.Command == "" { // Skip empty commands, see https://github.com/ddworken/hishtory/issues/279 continue } m, err := structToMap(*entry) if err != nil { return err } delete(m, "device_id") delete(m, "entry_id") j, err := json.Marshal(m) if err != nil { return err } _, err = w.Write(j) if err != nil { return err } _, err = w.Write([]byte("\n")) if err != nil { return err } } offset += chunkSize } return nil } func init() { rootCmd.AddCommand(exportJsonCmd) }