# HG changeset patch # User Mikael Berthe # Date 1539516009 -7200 # Node ID e918b7e63748817dde583a026fba08a6e365ad49 # Parent 730377b4449f16685dcb2cf769ca7e7f6acb18f5 Add JSON output diff -r 730377b4449f -r e918b7e63748 goduf.go --- a/goduf.go Sat Oct 13 21:44:16 2018 +0200 +++ b/goduf.go Sun Oct 14 13:20:09 2018 +0200 @@ -51,6 +51,22 @@ partialChecksum ) +// Results contains the results of the duplicates search +type Results struct { + Groups []ResultSet `json:"groups"` + Duplicates uint `json:"duplicates"` + NumberOfSets uint `json:"number_of_sets"` + RedundantDataSize uint64 `json:"redundant_data_size"` + RedundantDataSizeH string `json:"redundant_data_size_h"` + TotalFileCount uint `json:"total_file_count"` +} + +// ResultSet contains a group of identical duplicate files +type ResultSet struct { + Size uint64 `json:"size"` // Size of each item + Paths []string `json:"paths"` // List of file paths +} + type fileObj struct { //Unique bool FilePath string @@ -455,6 +471,7 @@ func main() { var verbose bool var summary bool + var outToJSON bool var skipPartial bool var ignoreEmpty bool @@ -466,6 +483,7 @@ // Command line parameters parsingg flag.BoolVar(&verbose, "verbose", false, "Be verbose (verbosity=1)") flag.BoolVar(&verbose, "v", false, "See --verbose") + flag.BoolVar(&outToJSON, "json", false, "Use JSON format for output") flag.BoolVar(&summary, "summary", false, "Do not display the duplicate list") flag.BoolVar(&summary, "s", false, "See --summary") flag.BoolVar(&skipPartial, "skip-partial", false, "Skip partial checksums") @@ -548,7 +566,7 @@ myLog.Println(3, "* Number of match groups:", len(result)) - // Done! Dump dupes + // Done! Prepare results data if len(result) > 0 && !summary { myLog.Println(1, "* Dupes:") } @@ -560,37 +578,23 @@ // Sort groups by increasing size (of the duplicated files) sort.Sort(byGroupFileSize(result)) - var dupeSize uint64 - data.cmpt = 0 - for i, l := range result { + var results Results + + for _, l := range result { size := uint64(l[0].Size()) // We do not count the size of the 1st item // so we get only duplicate size. - dupeSize += size * uint64(len(l)-1) - if !summary { - fmt.Printf("\nGroup #%d (%d files * %v):\n", i+1, - len(l), formatSize(size, true)) - } + results.RedundantDataSize += size * uint64(len(l)-1) + newSet := ResultSet{Size: size} for _, f := range l { - if !summary { - fmt.Println(f.FilePath) - } - data.cmpt++ + newSet.Paths = append(newSet.Paths, f.FilePath) + results.Duplicates++ } + results.Groups = append(results.Groups, newSet) } - summaryLevel := 1 // Default verbosity for the summary line - if summary == false { - // Add a trailing newline - if len(result) > 0 { - fmt.Println("") - } - } else { - // The summary is requested so we lower the verbosity level - summaryLevel = 0 - } + results.RedundantDataSizeH = formatSize(results.RedundantDataSize, true) + results.TotalFileCount = data.cmpt - myLog.Println(summaryLevel, "Final count:", data.cmpt, - "duplicate files in", len(result), "sets") - myLog.Println(summaryLevel, "Redundant data size:", - formatSize(dupeSize, false)) + // Output the results + displayResults(results, outToJSON, summary) } diff -r 730377b4449f -r e918b7e63748 output.go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/output.go Sun Oct 14 13:20:09 2018 +0200 @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2014-2018 Mikael Berthe + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +package main + +import ( + "encoding/json" + "fmt" +) + +func displayResults(results Results, jsonOutput bool, summaryOnly bool) { + if jsonOutput { + displayResultsJSON(results) + return + } + + if !summaryOnly { + for i, g := range results.Groups { + fmt.Printf("\nGroup #%d (%d files * %v):\n", i+1, + len(g.Paths), formatSize(g.Size, true)) + for _, f := range g.Paths { + fmt.Println(f) + } + } + } + + // We're done if we do not display statistics + if myLog.verbosity < 1 && !summaryOnly { + return + } + + // Add a trailing newline + if len(results.Groups) > 0 && myLog.verbosity > 0 { + fmt.Println() + } + myLog.Println(0, "Final count:", results.Duplicates, + "duplicate files in", len(results.Groups), "sets") + myLog.Println(0, "Redundant data size:", + formatSize(results.RedundantDataSize, false)) +} + +func displayResultsJSON(results Results) { + b, err := json.Marshal(results) + if err != nil { + panic(err) + } + fmt.Println(string(b)) +}