max_size_detector 0.1.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 +7 -0
- data/bin/max_size_detector +13 -0
- data/lib/max_size_detector/base.rb +200 -0
- data/lib/max_size_detector.rb +34 -0
- metadata +48 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1d7c8a074c02d399dc59d47e8853b64dc442c79b849c94308796604b97a6f73f
|
4
|
+
data.tar.gz: 7cb716a30b9656bf1f4a27d33d39e4e7deaaecac4a1ef4a3572f4ee69f93b4b2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e111c8248e0b585361418e2ed17e0a439c9b6155c58c17b11384560b50b03c75385dadfa4f74cc3ec1399785d76c9479558ecdbb78e51591887cd0349a3593ba
|
7
|
+
data.tar.gz: fbcf48a35555abc53df666832c0a6bb4a2aeee5e27e0619989b854b649613cc569c6ec2f2149a1c1c93ab7d345a943c9fa0e69470b12355adb7c696cfc6bf5f4
|
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "max_size_detector"
|
4
|
+
|
5
|
+
file = ARGV[0]&.strip || "input.txt"
|
6
|
+
max_size = if file.to_i.zero?
|
7
|
+
ARGV[1]&.strip || MaxSizeDetector::FILES_MAX_SIZE
|
8
|
+
else
|
9
|
+
file
|
10
|
+
end
|
11
|
+
file = "input.txt" if file.to_i.positive?
|
12
|
+
|
13
|
+
MaxSizeDetector.run(file: file, max_size: max_size)
|
@@ -0,0 +1,200 @@
|
|
1
|
+
require "json"
|
2
|
+
require "open-uri"
|
3
|
+
|
4
|
+
class MaxSizeDetector
|
5
|
+
class Base
|
6
|
+
attr_reader :input_file, :lines, :files, :directories, :output
|
7
|
+
|
8
|
+
def initialize(**opts)
|
9
|
+
filename = opts[:filename] || opts[:file]
|
10
|
+
@input_file = open(filename)
|
11
|
+
@max_size = opts[:max_size].to_i
|
12
|
+
@lines = Array.new
|
13
|
+
@files = Hash.new
|
14
|
+
@output = Hash.new
|
15
|
+
|
16
|
+
rescue => error
|
17
|
+
print " FAILED!\n#{error}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def extract!
|
21
|
+
return unless @input_file
|
22
|
+
|
23
|
+
extract_lines!
|
24
|
+
extract_files!
|
25
|
+
end
|
26
|
+
|
27
|
+
def process!
|
28
|
+
return unless @input_file
|
29
|
+
|
30
|
+
files_within_max_size = extract_files_by_max_size
|
31
|
+
grouped = group_by(hash_key: :parent_directory, files: files_within_max_size)
|
32
|
+
content_to_hash!(grouped)
|
33
|
+
|
34
|
+
@output = extract_files_by_max_size(files: grouped)
|
35
|
+
output_within_max_size!
|
36
|
+
end
|
37
|
+
|
38
|
+
def show_output
|
39
|
+
JSON.pretty_generate(JSON.parse(@output.to_json))
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
|
44
|
+
def extract_lines!
|
45
|
+
@lines = @input_file.readlines.map do |line|
|
46
|
+
line_str = line.to_s
|
47
|
+
line_str.end_with?("\n") ? line_str[0..-2] : line_str
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def extract_files!
|
52
|
+
keys = {}
|
53
|
+
@lines.each_with_index do |line, idx|
|
54
|
+
next unless file?(line)
|
55
|
+
|
56
|
+
parts = extract_file(line)
|
57
|
+
filename = parts.keys.first
|
58
|
+
filename!(keys, filename)
|
59
|
+
|
60
|
+
file = init_file(filename)
|
61
|
+
file_hash = file[filename]
|
62
|
+
file_hash[:size] = parts[filename]
|
63
|
+
|
64
|
+
parent_directory!(file_hash, idx)
|
65
|
+
|
66
|
+
@files.merge!(file)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def output_within_max_size!
|
71
|
+
new_output = Array.new
|
72
|
+
@output.to_a.repeated_combination(2) do |combi|
|
73
|
+
a = combi.first
|
74
|
+
b = combi.last
|
75
|
+
next if a == b
|
76
|
+
|
77
|
+
a_val = a[1]
|
78
|
+
b_val = b[1]
|
79
|
+
total = a_val[:size].to_i + b_val[:size].to_i
|
80
|
+
next if total > @max_size
|
81
|
+
|
82
|
+
c = new_total = nil
|
83
|
+
@output.each do |key, val|
|
84
|
+
next unless percent_up?(val[:size].to_i + total, percent: 80)
|
85
|
+
|
86
|
+
c = [key, val]
|
87
|
+
new_total = val[:size].to_i + total
|
88
|
+
break
|
89
|
+
end
|
90
|
+
|
91
|
+
if new_total && new_total < @max_size && a[0] != c[0] && b[0] != c[0]
|
92
|
+
new_output << Hash[
|
93
|
+
a[0] => a_val,
|
94
|
+
b[0] => b_val,
|
95
|
+
c[0] => c[1],
|
96
|
+
total: new_total
|
97
|
+
]
|
98
|
+
elsif percent_up?(total, percent: 80)
|
99
|
+
new_output << Hash[
|
100
|
+
a[0] => a_val,
|
101
|
+
b[0] => b_val,
|
102
|
+
total: total
|
103
|
+
]
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
@output = new_output.sort_by { |no| -no[:total] }
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def directory?(command)
|
113
|
+
return false if command.start_with?("$")
|
114
|
+
|
115
|
+
command.include?("dir ")
|
116
|
+
end
|
117
|
+
|
118
|
+
def file?(command)
|
119
|
+
return false if directory?(command) ||
|
120
|
+
command.start_with?("$")
|
121
|
+
|
122
|
+
extract_file(command).values.first.to_i.positive?
|
123
|
+
end
|
124
|
+
|
125
|
+
def sanitize_string(str)
|
126
|
+
str.delete("$").strip
|
127
|
+
end
|
128
|
+
|
129
|
+
def extract_parts(command)
|
130
|
+
sanitize_string(command).split(" ")
|
131
|
+
end
|
132
|
+
|
133
|
+
def extract_file(command)
|
134
|
+
parts = extract_parts(command)
|
135
|
+
|
136
|
+
Hash[
|
137
|
+
parts.last.to_s => parts.first.to_i
|
138
|
+
]
|
139
|
+
end
|
140
|
+
|
141
|
+
def filename!(hash, key)
|
142
|
+
hash[key] = hash.key?(key) ? hash[key] + 1 : 1
|
143
|
+
return unless hash[key] > 1
|
144
|
+
|
145
|
+
key += "-#{hash[key]}"
|
146
|
+
end
|
147
|
+
|
148
|
+
def init_file(key)
|
149
|
+
Hash[
|
150
|
+
key => Hash[
|
151
|
+
parent_directory: nil,
|
152
|
+
]
|
153
|
+
]
|
154
|
+
end
|
155
|
+
|
156
|
+
def parent_directory!(file_hash, idx)
|
157
|
+
ctr = 1
|
158
|
+
while file_hash[:parent_directory].nil? do
|
159
|
+
command = sanitize_string(@lines[idx - ctr])
|
160
|
+
ctr += 1
|
161
|
+
if command == "ls"
|
162
|
+
command = sanitize_string(@lines[idx - ctr])
|
163
|
+
file_hash[:parent_directory] = command.split(" ").last.to_s
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def group_by(files: @files, hash_key: :parent_directory)
|
169
|
+
files.group_by { |_key, val| val[hash_key] }.transform_values(&:flatten)
|
170
|
+
end
|
171
|
+
|
172
|
+
def extract_files_by_max_size(files: @files)
|
173
|
+
within_max_size = Hash.new
|
174
|
+
files.each do |key, val|
|
175
|
+
new_val = val.clone
|
176
|
+
new_val = Hash[*new_val] unless new_val.is_a?(Hash)
|
177
|
+
next if new_val[:size].to_i > @max_size
|
178
|
+
|
179
|
+
within_max_size.merge!(key => new_val)
|
180
|
+
end
|
181
|
+
within_max_size
|
182
|
+
end
|
183
|
+
|
184
|
+
def content_to_hash!(grouped)
|
185
|
+
grouped.each do |key, val|
|
186
|
+
val_h = val.each_slice(2).to_h
|
187
|
+
grouped[key] = Hash.new unless grouped[key].is_a?(Hash)
|
188
|
+
group_h = grouped[key]
|
189
|
+
group_h[:files] = val_h.map { |k, v| [k, v[:size]] }.to_h
|
190
|
+
group_h[:size] = group_h[:files].values.sum
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def percent_up?(num, percent: 90)
|
195
|
+
percentage = (num.to_f / @max_size.to_f) * 100
|
196
|
+
percentage.to_i > percent
|
197
|
+
end
|
198
|
+
|
199
|
+
end
|
200
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class MaxSizeDetector
|
2
|
+
FILES_MAX_SIZE = 100_000
|
3
|
+
|
4
|
+
def self.run(**opts)
|
5
|
+
file = opts[:file] || opts[:filename]
|
6
|
+
max_size = opts[:max_size]
|
7
|
+
|
8
|
+
print "Opening file #{file} ..."
|
9
|
+
base = Base.new(**opts)
|
10
|
+
return puts "" if base.input_file.nil?
|
11
|
+
|
12
|
+
random_done!
|
13
|
+
|
14
|
+
print "Extracting file structure ..."
|
15
|
+
base.extract!
|
16
|
+
random_done!
|
17
|
+
|
18
|
+
print "Finding directories up to #{max_size} ..."
|
19
|
+
base.process!
|
20
|
+
random_done!
|
21
|
+
|
22
|
+
puts "Output:"
|
23
|
+
puts base.show_output
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def self.random_done!
|
29
|
+
sleep(rand(2..7))
|
30
|
+
print " DONE!\n"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
require "max_size_detector/base"
|
metadata
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: max_size_detector
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- MarLo MoraLes
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-02-09 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: This gem allows you to analyze an input file (contains several terminal
|
14
|
+
commands and output related to files and directories) and finally detect all directories
|
15
|
+
candidate for deletion based on the maximum size.
|
16
|
+
email: moralesmarlo@hotmail.com
|
17
|
+
executables:
|
18
|
+
- max_size_detector
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- bin/max_size_detector
|
23
|
+
- lib/max_size_detector.rb
|
24
|
+
- lib/max_size_detector/base.rb
|
25
|
+
homepage: https://rubygems.org/gems/ruby_max_size_detector
|
26
|
+
licenses:
|
27
|
+
- MIT
|
28
|
+
metadata: {}
|
29
|
+
post_install_message:
|
30
|
+
rdoc_options: []
|
31
|
+
require_paths:
|
32
|
+
- lib
|
33
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
34
|
+
requirements:
|
35
|
+
- - ">="
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
requirements: []
|
44
|
+
rubygems_version: 3.3.7
|
45
|
+
signing_key:
|
46
|
+
specification_version: 4
|
47
|
+
summary: Ruby Max Size Detector
|
48
|
+
test_files: []
|