imagebackup 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fc81529419a0623c0598dabfbba9e4b5806b62a9dfa8ccd3eb9310912157b11b
4
- data.tar.gz: 650bfa77a3adfadc530c9466261f077b901f9b00e693180dd00d93978586ddfa
3
+ metadata.gz: c4a1d4dd786b4165fd4812dea1de48ef9ad9ad9040e2b4c572f633117e7147f9
4
+ data.tar.gz: 67d0e990a7491fee092a0b58386b218a52635ae1f68a79608dca347c791d8814
5
5
  SHA512:
6
- metadata.gz: ad5fe5bf394bb6282b772683aac8c66a18ff9b4fb58ea67bfaed17f0a19ff844ff6f77afa72cd1c0e5bfa8c463ca0d9de317f1c43e8b88089c918a1f9ac148ef
7
- data.tar.gz: b1fb8c3bf729427c2de5f34a79bb924ec465679f1b85b68d0acecf0b8fb9282468777bcaa0ca93f2e988cf479f5c8dc649bf66006a7becc973de24ffb619ca55
6
+ metadata.gz: 9b0b396b58101630b0c8390e9b0a6b8e139774b29d775136518becc866157bc66245682be814fc299b79095147f00c53d15a13079017fdc73b2973a8148aa511
7
+ data.tar.gz: d6c1d1dadc59c952dfca3d99f559fc69538459cde68d6268914a5e25bb4668fe5ec05d8e4f6e4d6914744cc91623331c79556bc3fbfc3b96c33d7322a9b7e38f
data/Gemfile CHANGED
@@ -1,7 +1,9 @@
1
- source "https://rubygems.org"
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in imagebackup.gemspec
4
6
  gemspec
5
7
 
6
- gem "rake", "~> 12.0"
7
- gem "rspec", "~> 3.0"
8
+ gem 'rake', '~> 12.0'
9
+ gem 'rspec', '~> 3.0'
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
3
5
 
4
6
  RSpec::Core::RakeTask.new(:spec)
5
7
 
6
- task :default => :spec
8
+ task default: :spec
data/bin/console CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require "bundler/setup"
4
- require "imagebackup"
4
+ require 'bundler/setup'
5
+ require 'imagebackup'
5
6
 
6
7
  # You can add fixtures and/or initialization code here to make experimenting
7
8
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +11,5 @@ require "imagebackup"
10
11
  # require "pry"
11
12
  # Pry.start
12
13
 
13
- require "irb"
14
+ require 'irb'
14
15
  IRB.start(__FILE__)
data/imagebackup.gemspec CHANGED
@@ -1,31 +1,33 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'lib/imagebackup/version'
2
4
 
3
5
  Gem::Specification.new do |spec|
4
- spec.name = "imagebackup"
6
+ spec.name = 'imagebackup'
5
7
  spec.version = Imagebackup::VERSION
6
- spec.authors = ["adrian-sal-kennedy"]
7
- spec.email = ["adrian.sal.kennedy@gmail.com"]
8
+ spec.authors = ['adrian-sal-kennedy']
9
+ spec.email = ['adrian.sal.kennedy@gmail.com']
8
10
 
9
- spec.summary = %q{A simple CLI app to backup all pics and vids from current folder to a destination in yyyy-mm-dd folders.}
10
- spec.description = %q{Uses Exiv2 and ffprobe to find creation dates for media types it finds.}
11
- spec.homepage = "https://github.com/adrian-sal-kennedy/imagebackup"
12
- spec.license = "MIT"
13
- spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
11
+ spec.summary = 'A simple CLI app to backup all pics and vids from current folder to a destination in yyyy-mm-dd folders.'
12
+ spec.description = 'Uses Exiv2 and ffprobe to find creation dates for media types it finds.'
13
+ spec.homepage = 'https://github.com/adrian-sal-kennedy/imagebackup'
14
+ spec.license = 'MIT'
15
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
14
16
 
15
17
  # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
16
18
 
17
- spec.metadata["homepage_uri"] = spec.homepage
19
+ spec.metadata['homepage_uri'] = spec.homepage
18
20
  # spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
19
21
  # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
20
22
 
21
23
  # Specify which files should be added to the gem when it is released.
22
24
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
25
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
24
26
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
27
  end
26
- spec.bindir = "exe"
28
+ spec.bindir = 'exe'
27
29
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
- spec.require_paths = ["lib"]
30
+ spec.require_paths = ['lib']
29
31
 
30
32
  spec.add_dependency 'exiv2'
31
33
  spec.add_dependency 'ffprober'
@@ -1,5 +1,7 @@
1
1
  require 'csv'
2
2
 
3
+ # FileTypes is a very simple file class to store and retrieve the list of files
4
+ # we are interested in backing up.
3
5
  class FileTypes
4
6
  def self.list
5
7
  file_list = []
@@ -7,11 +9,11 @@ class FileTypes
7
9
  file_list << "**/*.#{csv[0]}"
8
10
  file_list << "**/*.#{csv[0].upcase}"
9
11
  end
10
- return file_list
12
+ file_list
11
13
  end
12
14
 
13
- def self.add(ext=nil,type=nil)
14
- unless ext
15
+ def self.add(ext = nil, type = nil)
16
+ unless ext
15
17
  puts 'please enter the file type\'s extension, with or without the dot.'
16
18
  ext = gets.strip
17
19
  end
@@ -19,12 +21,13 @@ class FileTypes
19
21
  puts 'please enter "movie" or "pic" so we know what we\'re working with.'
20
22
  type = gets.strip
21
23
  end
22
- ext = ext.to_s.gsub(/[*."]/,'')
23
- p type
24
- type = (type.downcase.include?('m')) ? "movie" : "pic"
24
+ ext = ext.to_s.gsub(/[*."]/, '')
25
+ type = type.downcase.include?('m') ? 'movie' : 'pic'
25
26
  puts "opening file \"#{File.dirname(__FILE__)}/filetypes.csv\""
26
- CSV.open("#{File.dirname(__FILE__)}/filetypes.csv","a") do |csv|
27
- p csv << [ext,type]
27
+ CSV.open("#{File.dirname(__FILE__)}/filetypes.csv", 'a') do |csv|
28
+ csv << [ext, type]
28
29
  end
30
+ puts 'New file types registered.'
31
+ exit
29
32
  end
30
33
  end
data/lib/imagebackup.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+
2
3
  require_relative 'imagebackup/version'
3
4
 
4
5
  require_relative 'classes/filetypes'
@@ -11,56 +12,46 @@ require 'exiv2'
11
12
  require 'fileutils'
12
13
  require 'ffprober'
13
14
 
14
- def main_loop(dest,dryrun=true,file_op="copy")#,move=nil,link=nil)
15
+ def main_loop(dest, dryrun = true, file_op = 'copy')
15
16
  file_types = FileTypes.list
16
17
  Dir.glob(file_types).reverse_each do |f|
17
-
18
18
  file = "#{Dir.pwd}/#{f}"
19
19
 
20
- parms = build_paths(dest,file,get_dates(file))
20
+ parms = build_paths(dest, file, get_dates(file))
21
21
  outfile = parms[0]
22
22
  destpath = parms[1]
23
23
 
24
- copy_pic(file,outfile,destpath,dryrun,file_op)#,move,link)
25
-
24
+ copy_pic(file, outfile, destpath, dryrun, file_op)
26
25
  end
27
26
  end
28
27
 
29
- # main_loop(ARGV[0])
30
-
31
28
  dryrun = true
32
- # link = false
33
- # move = false
34
- file_op = "cp" # or "mv" or "ln_s"
29
+ file_op = 'cp' # or "mv" or "ln_s"
35
30
 
36
- if (ARGV & ['-m','--move']).any?
37
- # move = true
38
- file_op = "mv"
31
+ if (ARGV & ['-m', '--move']).any?
32
+ file_op = 'mv'
39
33
  ARGV.delete('-m')
40
34
  ARGV.delete('--move')
41
35
  end
42
- if (ARGV & ['-l','--link']).any?
43
- # link = true
44
- file_op = "ln_s"
36
+ if (ARGV & ['-l', '--link']).any?
37
+ file_op = 'ln_s'
45
38
  ARGV.delete('-l')
46
39
  ARGV.delete('--link')
47
40
  end
48
41
  if ARGV.include?('-a')
49
- ext=ARGV[ARGV.index('-a')+1]
50
- type=ARGV[ARGV.index('-a')+2]
51
- ARGV.slice!(ARGV.index('-a')..ARGV.index('-a')+2)
42
+ ext = ARGV[ARGV.index('-a') + 1]
43
+ type = ARGV[ARGV.index('-a') + 2]
44
+ ARGV.slice!(ARGV.index('-a')..ARGV.index('-a') + 2)
52
45
  end
53
46
  if ARGV.include?('--add-filetype')
54
- ext=ARGV[ARGV.index('--add-filetype')+1]
55
- type=ARGV[ARGV.index('--add-filetype')+2]
56
- ARGV.slice!(ARGV.index('--add-filetype')..ARGV.index('--add-filetype')+2)
57
- end
58
- if ext
59
- FileTypes.add(ext,type)
47
+ ext = ARGV[ARGV.index('--add-filetype') + 1]
48
+ type = ARGV[ARGV.index('--add-filetype') + 2]
49
+ ARGV.slice!(ARGV.index('--add-filetype')..ARGV.index('--add-filetype') + 2)
60
50
  end
61
- if (ARGV & ['-n','--dry-run']).any?
51
+ FileTypes.add(ext, type) if ext
52
+ if (ARGV & ['-n', '--dry-run']).any?
62
53
  dryrun = true
63
- puts "Doing a dry run - no operations will happen."
54
+ puts 'Doing a dry run - no operations will happen.'
64
55
  sleep 1
65
56
  ARGV.delete('-n')
66
57
  ARGV.delete('--dry-run')
@@ -68,16 +59,15 @@ else
68
59
  dryrun = false
69
60
  end
70
61
 
71
- if (ARGV & ['-h','--help','-?']).any?
72
- display_help()
73
- end
62
+ display_help if (ARGV & ['-h', '--help', '-?']).any?
74
63
 
75
64
  if ARGV[0].to_s == ''
76
- display_help()
65
+ display_help
66
+ elsif File.exist?(ARGV[0])
67
+ main_loop(ARGV[0], dryrun, file_op)
68
+ elsif ARGV[0][0] == '-'
69
+ puts "Invalid option!\n-----\n\n"
70
+ display_help
77
71
  else
78
- if File.exist?(ARGV[0])
79
- main_loop(ARGV[0],dryrun,file_op)
80
- else
81
- puts "Specified destination does not exist. Please create this folder first."
82
- end
83
- end
72
+ puts 'Specified destination does not exist. Please create this folder first.'
73
+ end
@@ -1,3 +1,3 @@
1
1
  module Imagebackup
2
- VERSION = "0.3.0"
2
+ VERSION = '0.3.1'
3
3
  end
@@ -1,7 +1,9 @@
1
- def build_paths(dest,file,date)
1
+ # frozen_string_literal: true
2
+
3
+ def build_paths(dest, file, date)
2
4
  date = get_dates(file)
3
5
  destpath = "#{dest}/#{date}"
4
- destpath = destpath.gsub('//','/')
6
+ destpath = destpath.gsub('//', '/')
5
7
  outfile = "#{destpath}/#{File.basename(file)}"
6
- return [outfile,destpath]
7
- end
8
+ [outfile, destpath]
9
+ end
@@ -1,29 +1,28 @@
1
- def process_file(file,outfile,dryrun=nil,file_op="cp")
1
+ def process_file(file, outfile, dryrun = nil, file_op = 'cp')
2
2
  if dryrun
3
3
  puts "pretending to #{file_op} \"#{file} to #{outfile}\""
4
4
  else
5
5
  puts "#{file_op}-ing \"#{file} to #{outfile}\"..."
6
- FileUtils.public_send(file_op,file,outfile)
7
- FileUtils.public_send(file_op,"#{file}.xmp",outfile,:force => true)
8
- if file_op == "cp"
9
- FileUtils.public_send(file_op,"#{file}.xmp",outfile)
6
+ FileUtils.public_send(file_op, file, outfile)
7
+ FileUtils.public_send(file_op, "#{file}.xmp", outfile, force: true)
8
+ if file_op == 'cp'
9
+ FileUtils.public_send(file_op, "#{file}.xmp", outfile)
10
10
  else
11
- FileUtils.public_send(file_op,"#{file}.xmp",outfile,:force => true)
11
+ FileUtils.public_send(file_op, "#{file}.xmp", outfile, force: true)
12
12
  end
13
13
  end
14
14
  end
15
15
 
16
- def copy_pic(file,outfile,destpath,dryrun=nil,file_op="cp") #,move=nil,link=nil)
17
- unless File.exist?(outfile)
16
+ def copy_pic(file, outfile, destpath, dryrun = nil, file_op = 'cp')
17
+ if File.exist?(outfile)
18
+ puts "\"#{outfile}\" already exists. Skipping..."
19
+ else
18
20
  unless dryrun
19
21
  unless File.exist?(destpath)
20
22
  puts "creating folder \"#{destpath}\""
21
23
  FileUtils.mkdir_p(destpath)
22
- else
23
24
  end
24
25
  end
25
- process_file(file,outfile,dryrun,file_op)
26
- else
27
- puts "\"#{outfile}\" already exists. Skipping..."
26
+ process_file(file, outfile, dryrun, file_op)
28
27
  end
29
28
  end
@@ -1,82 +1,82 @@
1
1
  def display_help
2
- print <<EOF
3
- ===== ImageBackup =====
2
+ print <<~HELPFILE
3
+ ===== ImageBackup =====
4
4
 
5
- Keep your photos and videos organized by date.
5
+ Keep your photos and videos organized by date.
6
6
 
7
- A simple terminal app to crawl a folder (usually a camera card's DCIM folder) for pictures and videos, and pop them in dated folders to your destination folder of choice. Uses exif data when available, creation_time, or the file's own creation date if nothing better is present.
7
+ A simple terminal app to crawl a folder (usually a camera card's DCIM folder) for pictures and videos, and pop them in dated folders to your destination folder of choice. Uses exif data when available, creation_time, or the file's own creation date if nothing better is present.
8
8
 
9
- Will also copy over any xmp sidecar files found, not overwriting.
9
+ Will also copy over any xmp sidecar files found, not overwriting.
10
10
 
11
- Options:
11
+ Options:
12
12
 
13
- -n, --dry-run Run without actually doing anything. Good for making sure
14
- things are working properly. This will also give you console
15
- output which helps identify unreadable files.
13
+ -n, --dry-run Run without actually doing anything. Good for making sure
14
+ things are working properly. This will also give you console
15
+ output which helps identify unreadable files.
16
16
 
17
- -a, --add-filetype <extension> <type> This will add a custom file type to the list of files it's
18
- looking for. If you have an arcane digital camera (we
19
- currently support canon, sony, pentax but new stuff comes out
20
- all the time), this will allow you to add your raw files.
21
- You can also access *filetypes.csv* and add them manually,
22
- but ensure there's a blank line at the end or this program
23
- may behave badly.
17
+ -a, --add-filetype <extension> <type> This will add a custom file type to the list of files it's
18
+ looking for. If you have an arcane digital camera (we
19
+ currently support canon, sony, pentax but new stuff comes out
20
+ all the time), this will allow you to add your raw files.
21
+ You can also access *filetypes.csv* and add them manually,
22
+ but ensure there's a blank line at the end or this program
23
+ may behave badly.
24
24
 
25
- -m will move (deleting the original), which is probably not a
26
- good idea in most cases but still useful at times.
25
+ -m will move (deleting the original), which is probably not a
26
+ good idea in most cases but still useful at times.
27
27
 
28
- Usage:
28
+ Usage:
29
29
 
30
- - To backup a camera card:
30
+ - To backup a camera card:
31
31
 
32
- $ cd /media/username/EOS_DIGITAL/DCIM
33
- $ imagebackup.rb ~/Photos/raw
32
+ $ cd /media/username/EOS_DIGITAL/DCIM
33
+ $ imagebackup.rb ~/Photos/raw
34
34
 
35
- This will search all files within the DCIM folder, check them with either exiv2 (for stills) or ffprobe (for videos) and retrieve their creation dates.
36
- It will then copy them to a folder of the form ~/Photos/raw/<yyyy>-<mm>-<dd>
37
- If it's unable to find metadata in a file it will look at the file's creation time attribute, which is less reliable but usually ok.
35
+ This will search all files within the DCIM folder, check them with either exiv2 (for stills) or ffprobe (for videos) and retrieve their creation dates.
36
+ It will then copy them to a folder of the form ~/Photos/raw/<yyyy>-<mm>-<dd>
37
+ If it's unable to find metadata in a file it will look at the file's creation time attribute, which is less reliable but usually ok.
38
38
 
39
- - To register a new file type:
39
+ - To register a new file type:
40
40
 
41
- $ imagebackup.rb --add-filetype orf pic
42
- or
43
- $ imagebackup.rb -a orf pic
41
+ $ imagebackup.rb --add-filetype orf pic
42
+ or
43
+ $ imagebackup.rb -a orf pic
44
44
 
45
- This will work with *.ORF, orf, ".orf" as it will strip off any unnecessary characters. It is case-insensitive.
45
+ This will work with *.ORF, orf, ".orf" as it will strip off any unnecessary characters. It is case-insensitive.
46
46
 
47
- - To do a dry run, checking each file and destination but not actually copying:
47
+ - To do a dry run, checking each file and destination but not actually copying:
48
48
 
49
- $ imagebackup.rb -n ~/Photos/raw
50
- or
51
- $ imagebackup.rb ~/Photos/raw --dry-run
49
+ $ imagebackup.rb -n ~/Photos/raw
50
+ or
51
+ $ imagebackup.rb ~/Photos/raw --dry-run
52
52
 
53
- - To move files instead of copying them (careful!):
53
+ - To move files instead of copying them (careful!):
54
54
 
55
- $ imagebackup.rb -m ~/Photos/raw
56
- or
57
- $ imagebackup.rb --move ~/Photos/raw
55
+ $ imagebackup.rb -m ~/Photos/raw
56
+ or
57
+ $ imagebackup.rb --move ~/Photos/raw
58
58
 
59
- - To make symbolic links instead of copying files:
59
+ - To make symbolic links instead of copying files:
60
60
 
61
- $ imagebackup.rb -l ~/Photos/raw
62
- or
63
- $ imagebackup.rb --link ~/Photos/raw
61
+ $ imagebackup.rb -l ~/Photos/raw
62
+ or
63
+ $ imagebackup.rb --link ~/Photos/raw
64
64
 
65
- This mode can be useful if you want to operate on the files in one place but keep them on their media. Particularly useful for large movie files.
65
+ This mode can be useful if you want to operate on the files in one place but keep them on their media. Particularly useful for large movie files.
66
66
 
67
- Dependencies:
67
+ Dependencies:
68
68
 
69
- Ruby v2.3.0 or greater, plus gems:
70
- - exiv2
71
- - ffprober
69
+ Ruby v2.3.0 or greater, plus gems:
70
+ - exiv2
71
+ - ffprober
72
72
 
73
- Ruby modules:
74
- - fileutils
73
+ Ruby modules:
74
+ - fileutils
75
75
 
76
- Bundler should handle all these dependencies. If for some reason it doesn't you can run this in terminal:
77
- $ gem install exiv2 ffprober
76
+ Bundler should handle all these dependencies. If for some reason it doesn't you can run this in terminal:
77
+ $ gem install exiv2 ffprober
78
78
 
79
- EOF
79
+ HELPFILE
80
80
 
81
- exit(0)
82
- end
81
+ exit(0)
82
+ end
@@ -3,15 +3,15 @@ def get_dates(file)
3
3
  image = Exiv2::ImageFactory.open(file)
4
4
  image.read_metadata
5
5
  date = image.exif_data.find { |v| v[0] == 'Exif.Image.DateTime' }
6
- date = date[1].split[0].gsub(':','-')
7
- rescue => exiv2_no_exifdata
6
+ date = date[1].split[0].gsub(':', '-')
7
+ rescue StandardError
8
8
  begin
9
9
  probe = Ffprober::Parser.from_file(file)
10
10
  date = probe.format.tags[:creation_time].split('T')[0]
11
- rescue => invalid_or_corrupt_file
11
+ rescue StandardError
12
12
  fileobj = File.new(file)
13
13
  date = "#{fileobj.stat.ctime.year}-#{fileobj.stat.ctime.month}-#{fileobj.stat.ctime.day}"
14
14
  end
15
15
  end
16
- return date
17
- end
16
+ date
17
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: imagebackup
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - adrian-sal-kennedy