android_file_sorter 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/android_file_sorter +5 -0
- data/lib/android_file_sorter.rb +20 -0
- data/lib/android_file_sorter/description.rb +32 -0
- data/lib/android_file_sorter/directory_statistic.rb +48 -0
- data/lib/android_file_sorter/entries_validator.rb +57 -0
- data/lib/android_file_sorter/file_renamer.rb +86 -0
- metadata +71 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d9fb4eaf951e6d95590e161669d09c9f5a21ec28
|
4
|
+
data.tar.gz: ef6020b61e28e6c08c15d6a707c8e35c4b709971
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 990f7426d0d7c7aa6b249a2ea1cd75c2f6bc7d0b27f5cbca213dcf0237a43f00a8d19e7ae8b39f5552da2c4e887563cbd16ea617f5c545eb3e92937be977f49e
|
7
|
+
data.tar.gz: 7de11f598f8a04d95899a013c4e3888f59236ebfdc23dff6eea89e2b27f5fe13f7db9676cb6205a4add28da537f614b2f34e2e2955407b88d1d8b2998d62ed12
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "android_file_sorter/directory_statistic"
|
2
|
+
require "android_file_sorter/entries_validator"
|
3
|
+
require "android_file_sorter/description"
|
4
|
+
require "android_file_sorter/file_renamer"
|
5
|
+
require "time"
|
6
|
+
|
7
|
+
class AndroidFileSorter
|
8
|
+
|
9
|
+
def initialize(current_directory)
|
10
|
+
@cwd = current_directory
|
11
|
+
end
|
12
|
+
|
13
|
+
def rename_all
|
14
|
+
EntriesValidator.new(@cwd).validate_entries
|
15
|
+
DirectoryStatistic.new(@cwd).render_stats
|
16
|
+
FileRenamer.new(@cwd).process_files
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Description
|
2
|
+
|
3
|
+
def documentation
|
4
|
+
puts <<-DOC
|
5
|
+
|
6
|
+
How do your files get renamed?
|
7
|
+
------------------------------
|
8
|
+
You are naming filesets, not files. That means that if you have eleven files recorded on the
|
9
|
+
same day, after your provide your new name e.g. "My birthday", all files recorded on the same day
|
10
|
+
will be renamed to "My_birthday".
|
11
|
+
For convenience, AnroidFileSorter will give each file a number "My_birthday_1" and remove a time stamp.
|
12
|
+
This way, you will still know the order in which files were recorded (pictures or videos taken).
|
13
|
+
Final name will include a date stamp however, so our example files will be named
|
14
|
+
"My_birthday_2015-08-15_Tue_1".
|
15
|
+
|
16
|
+
DOC
|
17
|
+
end
|
18
|
+
|
19
|
+
def options
|
20
|
+
puts <<-OPTIONS
|
21
|
+
Proceed with renaming your files:
|
22
|
+
- [ l ] leave a fileset as is
|
23
|
+
- [ a ] let AFS name files for you
|
24
|
+
- [ d ] show documentation
|
25
|
+
- [ e ] exit program
|
26
|
+
- [ r ] rename files yourself
|
27
|
+
|
28
|
+
OPTIONS
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
class DirectoryStatistic
|
2
|
+
|
3
|
+
def initialize(current_directory)
|
4
|
+
@user_files = Dir.entries(current_directory).select { |file| ![ ".", "..", ".DS_Store"].include?(file) }
|
5
|
+
@stats = { dates: {},
|
6
|
+
formats: {},
|
7
|
+
sum: 0 }
|
8
|
+
end
|
9
|
+
|
10
|
+
def render_stats
|
11
|
+
compile_statistic
|
12
|
+
|
13
|
+
if @stats[:sum].zero?
|
14
|
+
puts "Your directory is empty. Please put some files in it."
|
15
|
+
exit
|
16
|
+
else
|
17
|
+
puts "Total number of all files: #{@stats[:sum]}"
|
18
|
+
puts "Formats:"
|
19
|
+
@stats[:formats].each { |format, count| puts(" #{format}: #{count}") }
|
20
|
+
puts "Dates:"
|
21
|
+
@stats[:dates].each { |date, count| puts(" #{date}: #{count}") }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def compile_statistic
|
28
|
+
@user_files.each do |file|
|
29
|
+
count_format(file.split(".").last.to_sym)
|
30
|
+
count_date(DateTime.parse(file.split("_").first))
|
31
|
+
@stats[:sum] += 1
|
32
|
+
end
|
33
|
+
@stats
|
34
|
+
end
|
35
|
+
|
36
|
+
def count_format(format)
|
37
|
+
formats = @stats[:formats]
|
38
|
+
@stats[:formats][format] = formats.has_key?(format) ? formats[format] + 1 : 1
|
39
|
+
end
|
40
|
+
|
41
|
+
def count_date(date_time)
|
42
|
+
date = date_time.strftime("%Y-%m-%d").to_sym
|
43
|
+
dates = @stats[:dates]
|
44
|
+
@stats[:dates][date] = dates.has_key?(date) ? dates[date] + 1 : 1
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
class EntriesValidator
|
2
|
+
|
3
|
+
def initialize(current_directory)
|
4
|
+
@cwd = current_directory
|
5
|
+
@valid_formats = [ "jpg", "mp4" ]
|
6
|
+
@system_files = [ ".", "..", ".DS_Store" ]
|
7
|
+
end
|
8
|
+
|
9
|
+
def validate_entries
|
10
|
+
user_files = Dir.entries(@cwd).select { |file| !@system_files.include?(file) }
|
11
|
+
filtered_entries = filter_entries(user_files)
|
12
|
+
if invalid_entries?(filtered_entries)
|
13
|
+
notify_user(filtered_entries)
|
14
|
+
exit
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def filter_entries(user_files)
|
21
|
+
invalid_entries = {
|
22
|
+
dirs: [],
|
23
|
+
invalid_formats: [],
|
24
|
+
invalid_lengths: []
|
25
|
+
}
|
26
|
+
user_files.each do |e|
|
27
|
+
if Dir.exist?(e)
|
28
|
+
invalid_entries[:dirs] << e
|
29
|
+
elsif !@valid_formats.include?(e.split(".").last)
|
30
|
+
invalid_entries[:invalid_formats] << e
|
31
|
+
elsif e.length != 19
|
32
|
+
invalid_entries[:invalid_lengths] << e
|
33
|
+
end
|
34
|
+
end
|
35
|
+
invalid_entries
|
36
|
+
end
|
37
|
+
|
38
|
+
def invalid_entries?(entries)
|
39
|
+
entries.values.each { |val| return true unless val.empty? }
|
40
|
+
false
|
41
|
+
end
|
42
|
+
|
43
|
+
def notify_user(entries)
|
44
|
+
dir_count = entries[:dirs].count
|
45
|
+
invalid_formats = entries[:invalid_formats].count
|
46
|
+
invalid_lengths = entries[:invalid_lengths].count
|
47
|
+
puts "Your directory must be empty."
|
48
|
+
puts "It must not contain any directories or files that are not images or videos."
|
49
|
+
puts "Currently your working directory contains:"
|
50
|
+
puts " directories: #{dir_count}" unless dir_count.zero?
|
51
|
+
puts " files with invalid formats: #{invalid_formats}" unless invalid_formats.zero?
|
52
|
+
puts " files with invalid lengths: #{invalid_lengths}" unless invalid_lengths.zero?
|
53
|
+
puts "Please empty your directory. Afterwards, copy your images into it."
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
@@ -0,0 +1,86 @@
|
|
1
|
+
class FileRenamer
|
2
|
+
include Description
|
3
|
+
|
4
|
+
def initialize(current_directory)
|
5
|
+
@cwd = current_directory
|
6
|
+
@user_files = Dir.entries(@cwd).select { |file| ![ ".", "..", ".DS_Store" ].include?(file) }
|
7
|
+
@filesets = collect_filesets
|
8
|
+
@file_dates = @filesets.keys
|
9
|
+
end
|
10
|
+
|
11
|
+
def process_files
|
12
|
+
documentation
|
13
|
+
rename_files
|
14
|
+
end
|
15
|
+
|
16
|
+
def rename_files
|
17
|
+
options
|
18
|
+
|
19
|
+
loop do
|
20
|
+
date = @file_dates.first
|
21
|
+
puts "Next file set: #{date}."
|
22
|
+
print ">> "
|
23
|
+
|
24
|
+
case gets.chomp
|
25
|
+
when "l"
|
26
|
+
@file_dates.shift
|
27
|
+
when "a"
|
28
|
+
@file_dates.shift
|
29
|
+
automatic_renaming(date)
|
30
|
+
when "d"
|
31
|
+
documentation
|
32
|
+
when "e"
|
33
|
+
puts "Exiting program."
|
34
|
+
exit
|
35
|
+
when "r"
|
36
|
+
@file_dates.shift
|
37
|
+
puts "Enter a fileset name:"
|
38
|
+
print ">> "
|
39
|
+
user_filename = gets.chomp.gsub(/\s/, "_")
|
40
|
+
user_renaming(date, user_filename)
|
41
|
+
else
|
42
|
+
puts "Enter one of the available options."
|
43
|
+
options
|
44
|
+
end
|
45
|
+
|
46
|
+
if @file_dates.empty?
|
47
|
+
puts "All of your files are renamed."
|
48
|
+
exit
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def automatic_renaming(date)
|
56
|
+
@filesets[date].inject(0) do |memo, file|
|
57
|
+
file_array = file.split(".")
|
58
|
+
timestamp, format = file_array.first, file_array.last
|
59
|
+
datetime = DateTime.parse(timestamp).strftime("%Y-%m-%d_%a")
|
60
|
+
new_filename = "#{datetime}_#{memo += 1}.#{format}"
|
61
|
+
File.rename(file, new_filename)
|
62
|
+
memo
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def user_renaming(date, user_filename)
|
67
|
+
@filesets[date].inject(0) do |memo, file|
|
68
|
+
file_array = file.split(".")
|
69
|
+
timestamp, format = file_array.first, file_array.last
|
70
|
+
day = DateTime.parse(timestamp).strftime("%a")
|
71
|
+
new_filename = "#{user_filename}_#{date}_#{day}_#{memo += 1}.#{format}"
|
72
|
+
File.rename(file, new_filename)
|
73
|
+
memo
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def collect_filesets
|
78
|
+
@user_files.each_with_object({}) do |file, obj|
|
79
|
+
date = DateTime.parse(file.split(".").first).strftime("%Y-%m-%d")
|
80
|
+
obj[date] = [] unless obj[date]
|
81
|
+
obj[date] << file
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: android_file_sorter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- dariodaic
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-08-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.1'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 3.1.7
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3.1'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 3.1.7
|
33
|
+
description: Tiny gem for managing files copied from Android OS 4.3.
|
34
|
+
email:
|
35
|
+
- dariodaic5.1@gmail.com
|
36
|
+
executables:
|
37
|
+
- android_file_sorter
|
38
|
+
extensions: []
|
39
|
+
extra_rdoc_files: []
|
40
|
+
files:
|
41
|
+
- bin/android_file_sorter
|
42
|
+
- lib/android_file_sorter.rb
|
43
|
+
- lib/android_file_sorter/description.rb
|
44
|
+
- lib/android_file_sorter/directory_statistic.rb
|
45
|
+
- lib/android_file_sorter/entries_validator.rb
|
46
|
+
- lib/android_file_sorter/file_renamer.rb
|
47
|
+
homepage:
|
48
|
+
licenses:
|
49
|
+
- MIT
|
50
|
+
metadata: {}
|
51
|
+
post_install_message:
|
52
|
+
rdoc_options: []
|
53
|
+
require_paths:
|
54
|
+
- lib
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: 2.2.0
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
requirements: []
|
66
|
+
rubyforge_project:
|
67
|
+
rubygems_version: 2.4.8
|
68
|
+
signing_key:
|
69
|
+
specification_version: 4
|
70
|
+
summary: Ruby script for renaming files copied from Android OS 4.3.
|
71
|
+
test_files: []
|