├── .gitignore ├── License ├── ReadMe.md └── boltdb-dump.go /.gitignore: -------------------------------------------------------------------------------- 1 | boltdb-dump 2 | *.db 3 | -------------------------------------------------------------------------------- /License: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Andrew Chilton 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /ReadMe.md: -------------------------------------------------------------------------------- 1 | # boltdb-dump # 2 | 3 | Command to dump a human-readable BoltDB to stdout. This works with buckets at any level, not just the top-level. 4 | 5 | Note: currently this will only be readable with string keys and values such as JSON. If you're using MsgPack or 6 | Protocol Buffers for your values, then this program won't do what you want (yet). 7 | 8 | ## Install ## 9 | 10 | ```sh 11 | go get -u github.com/chilts/boltdb-dump 12 | ``` 13 | 14 | ## Usage ## 15 | 16 | There are (currently) no options, nor anythin fancy. Just pass the db file you want to dump: 17 | 18 | ```sh 19 | boltdb-dump database.db 20 | ``` 21 | 22 | An example of a blog site with users and domains: 23 | 24 | ```sh 25 | [users] 26 | chilts 27 | {"UserName":"chilts","Email":"andychilton@gmail.com"} 28 | [domains] 29 | [chilts.org] 30 | [authors] 31 | andrew-chilton 32 | [posts] 33 | first-post 34 | {"PostName":"first-post","Title":"First Post","Content":"Hello, World!"} 35 | [blog.appsattic.com] 36 | [authors] 37 | andrew-chilton 38 | [posts] 39 | ``` 40 | 41 | ## Author ## 42 | 43 | [Andrew Chilton](https://chilts.org/) - [@andychilton](https://twitter.com/andychilton). 44 | 45 | ## License ## 46 | 47 | [MIT](https://chilts.mit-license.org/2016/). 48 | 49 | (Ends) 50 | -------------------------------------------------------------------------------- /boltdb-dump.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "strings" 7 | "time" 8 | 9 | "github.com/boltdb/bolt" 10 | ) 11 | 12 | func check(err error) { 13 | if err != nil { 14 | fmt.Printf("Error: %v\n", err) 15 | os.Exit(2) 16 | } 17 | } 18 | 19 | func dumpCursor(tx *bolt.Tx, c *bolt.Cursor, indent int) { 20 | for k, v := c.First(); k != nil; k, v = c.Next() { 21 | if v == nil { 22 | fmt.Printf(strings.Repeat(" ", indent-1)+"[%s]\n", k) 23 | newBucket := c.Bucket().Bucket(k) 24 | if newBucket == nil { 25 | // from the top-level cursor and not a cursor from a bucket 26 | newBucket = tx.Bucket(k) 27 | } 28 | newCursor := newBucket.Cursor() 29 | dumpCursor(tx, newCursor, indent+1) 30 | } else { 31 | fmt.Printf(strings.Repeat(" ", indent-1)+"%s\n", k) 32 | fmt.Printf(strings.Repeat(" ", indent-1)+" %s\n", v) 33 | } 34 | } 35 | } 36 | 37 | // Dump everything in the database. 38 | func dump(db *bolt.DB) error { 39 | return db.View(func(tx *bolt.Tx) error { 40 | c := tx.Cursor() 41 | dumpCursor(tx, c, 1) 42 | return nil 43 | }) 44 | } 45 | 46 | func main() { 47 | // check we have a filename 48 | if len(os.Args) < 2 { 49 | fmt.Printf("Usage: %s \n", os.Args[0]) 50 | os.Exit(2) 51 | } 52 | 53 | // the first arg is the database file 54 | filename := os.Args[1] 55 | 56 | // open this file 57 | opts := bolt.Options{ 58 | ReadOnly: true, 59 | Timeout: 1 * time.Second, 60 | } 61 | db, err := bolt.Open(filename, 0600, &opts) 62 | check(err) 63 | defer db.Close() 64 | 65 | // dump all keys 66 | dump(db) 67 | } 68 | --------------------------------------------------------------------------------