rdupes 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/exe/rdupes +4 -0
- data/lib/rdupes.rb +40 -12
- data/lib/rdupes/version.rb +1 -1
- data/rdupes.gemspec +1 -0
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 52c253e303c1b31d334dbaae5354cafc18397db2
|
4
|
+
data.tar.gz: 27bff2346e926eb9f483390048dcaff908a1f907
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce5fdaf876597b5e329db389b87c6b3144d886437f961ff3b22e7755c83a7e8c95159cac3887091ed89bc9579b9cb5e1c949afe90320be9efe9baf62125a8c1a
|
7
|
+
data.tar.gz: 3c235c3dd62631e8eb33088d4f5ef15f86246eb88317d4978fe319cbcafa7e9d5cd0181516791c9888dfe18621ca734fe071b33b68fe88d0dc44a74561b4e37a
|
data/exe/rdupes
CHANGED
@@ -12,6 +12,10 @@ opt_parser = OptionParser.new do |opts|
|
|
12
12
|
rdupe.add_reference_directory directory
|
13
13
|
end
|
14
14
|
|
15
|
+
opts.on("-d", "--dryrun", "Runs the analysis but without any file deletion") do |q|
|
16
|
+
rdupe.dry_run!
|
17
|
+
end
|
18
|
+
|
15
19
|
opts.on("-q", "--quiet", "Runs quietly") do |q|
|
16
20
|
rdupe.quiet!
|
17
21
|
end
|
data/lib/rdupes.rb
CHANGED
@@ -2,6 +2,7 @@ require "rdupes/version"
|
|
2
2
|
require 'logger'
|
3
3
|
require 'shellwords'
|
4
4
|
require 'tmpdir'
|
5
|
+
require 'colorize'
|
5
6
|
|
6
7
|
module Rdupes
|
7
8
|
class Finder
|
@@ -15,16 +16,24 @@ module Rdupes
|
|
15
16
|
@counters = Hash.new(0)
|
16
17
|
@quiet = false
|
17
18
|
@keep = false
|
19
|
+
@dry_run = false
|
18
20
|
end
|
19
21
|
|
20
22
|
def quiet!
|
23
|
+
@logger.debug "Enabling quiet mode"
|
21
24
|
@quiet = true
|
22
25
|
end
|
23
26
|
|
24
27
|
def keep!
|
28
|
+
@logger.debug "Enabling keep mode. Will keep the fdupes output"
|
25
29
|
@keep = true
|
26
30
|
end
|
27
31
|
|
32
|
+
def dry_run!
|
33
|
+
@logger.debug "Enabling dry run mode"
|
34
|
+
@dry_run = true
|
35
|
+
end
|
36
|
+
|
28
37
|
def add_reference_directory(directory)
|
29
38
|
directory_path = File.expand_path(directory)
|
30
39
|
@logger.debug "Adding #{directory_path} to the reference directories"
|
@@ -47,26 +56,37 @@ module Rdupes
|
|
47
56
|
raise 'No directories provided for duplicate search' if @search_directories.empty?
|
48
57
|
raise 'fdupes needs to be installed' unless command? 'fdupes'
|
49
58
|
|
50
|
-
|
51
|
-
|
52
|
-
puts "Reference directory: #{@reference_directories}"
|
53
|
-
end
|
59
|
+
say "Processing #{@search_directories}"
|
60
|
+
say "Reference directory: #{@reference_directories}"
|
54
61
|
|
55
62
|
Dir.mktmpdir do |dir|
|
56
|
-
|
63
|
+
fdupes_output = File.join(dir, 'duplicates.log')
|
57
64
|
# Redirect to file
|
58
|
-
cmd = "fdupes -rq #{directories_for_search.shelljoin} > #{
|
65
|
+
cmd = "fdupes -rq #{directories_for_search.shelljoin} > #{fdupes_output}"
|
59
66
|
@logger.debug "Executing: #{cmd}"
|
60
67
|
r = system cmd
|
61
68
|
raise "fdupe crashed " unless r
|
62
|
-
process_fdupes_result(
|
63
|
-
|
64
|
-
|
69
|
+
process_fdupes_result(fdupes_output)
|
70
|
+
|
71
|
+
if @keep
|
72
|
+
fdupes_output_copy = "#{Time.now.strftime('%Y-%m-%d_%H-%M-%S')}_duplicates.log"
|
73
|
+
say "Copying fdupes result to #{fdupes_output_copy}"
|
74
|
+
FileUtils.cp fdupes_output, fdupes_output_copy
|
75
|
+
end
|
76
|
+
|
77
|
+
say "Found #{@counters[:duplicate_groups]} duplicate groups"
|
78
|
+
say "Found #{@counters[:duplicate_entries]} duplicate entries"
|
79
|
+
say "Flagged #{@counters[:flag_for_delete]} files for deletion"
|
80
|
+
say "Deleted #{@counters[:deleted]} files"
|
65
81
|
end
|
66
82
|
end
|
67
83
|
|
68
84
|
private
|
69
85
|
|
86
|
+
def say(text)
|
87
|
+
puts text unless @quiet
|
88
|
+
end
|
89
|
+
|
70
90
|
def command?(command)
|
71
91
|
system("which #{ command} > /dev/null 2>&1")
|
72
92
|
end
|
@@ -91,18 +111,26 @@ module Rdupes
|
|
91
111
|
|
92
112
|
def handle_duplicate_group(duplicate_group)
|
93
113
|
@logger.debug "Handling group of #{duplicate_group.size} duplicates"
|
114
|
+
say "#{'==>'.blue} Group of #{duplicate_group.size} duplicates"
|
115
|
+
@counters[:duplicate_groups] += 1
|
116
|
+
@counters[:duplicate_entries] += duplicate_group.size
|
94
117
|
reference_files, duplicate_files = duplicate_group.partition do |f|
|
95
118
|
@reference_directories.any? { |rf| File.expand_path(f).start_with?(rf) }
|
96
119
|
end
|
97
120
|
# Keep the first duplicate if there is no reference file.
|
98
|
-
duplicate_files.shift if reference_files.empty?
|
121
|
+
say "- #{duplicate_files.shift}".green if reference_files.empty?
|
122
|
+
reference_files.each { |rf| say "- #{rf}".green }
|
99
123
|
duplicate_files.each { |dp| handle_duplicate_file(dp) }
|
100
124
|
end
|
101
125
|
|
102
126
|
def handle_duplicate_file(duplicate_file)
|
103
|
-
@counters[:deleted] += 1
|
104
127
|
@logger.debug "Handling duplicate #{duplicate_file}"
|
105
|
-
|
128
|
+
@counters[:flag_for_delete] += 1
|
129
|
+
say "- #{duplicate_file}".red
|
130
|
+
unless @dry_run
|
131
|
+
File.delete(duplicate_file)
|
132
|
+
@counters[:deleted] += 1
|
133
|
+
end
|
106
134
|
end
|
107
135
|
end
|
108
136
|
end
|
data/lib/rdupes/version.rb
CHANGED
data/rdupes.gemspec
CHANGED
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
20
|
spec.require_paths = ["lib"]
|
21
21
|
|
22
|
+
spec.add_dependency "colorize"
|
22
23
|
spec.add_development_dependency "bundler", "~> 1.13"
|
23
24
|
spec.add_development_dependency "rake", "~> 10.0"
|
24
25
|
spec.add_development_dependency "rspec", "~> 3.0"
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rdupes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Harold Waterkeyn
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-09-
|
11
|
+
date: 2016-09-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: colorize
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|