multi_exiftool 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/CHANGELOG +1 -1
  2. data/LICENSE +21 -0
  3. data/Manifest +16 -23
  4. data/README +77 -16
  5. data/Rakefile +17 -38
  6. data/examples/01_simple_reading.rb +13 -0
  7. data/examples/02_simple_writing.rb +19 -0
  8. data/examples/03_reading_using_groups.rb +28 -0
  9. data/lib/multi_exiftool.rb +6 -38
  10. data/lib/multi_exiftool/executable.rb +67 -0
  11. data/lib/multi_exiftool/reader.rb +60 -0
  12. data/lib/multi_exiftool/values.rb +60 -0
  13. data/lib/multi_exiftool/writer.rb +55 -0
  14. data/multi_exiftool.gemspec +25 -16
  15. data/test/helper.rb +27 -0
  16. data/test/test_reader.rb +135 -0
  17. data/test/test_values.rb +75 -0
  18. data/test/test_values_using_groups.rb +61 -0
  19. data/test/test_writer.rb +102 -0
  20. metadata +49 -47
  21. data/COPYING +0 -165
  22. data/data/fixtures/read_non_existing_file.stderr +0 -1
  23. data/data/fixtures/read_non_existing_file.stdout +0 -0
  24. data/data/fixtures/read_one_file.stderr +0 -0
  25. data/data/fixtures/read_one_file.stdout +0 -92
  26. data/data/fixtures/read_two_files.stderr +0 -0
  27. data/data/fixtures/read_two_files.stdout +0 -212
  28. data/data/regression/read_command.rb +0 -12
  29. data/data/regression/read_command.rb.out +0 -16
  30. data/data/regression/write_command.rb +0 -16
  31. data/data/regression/write_command.rb.out +0 -40
  32. data/lib/multi_exiftool/command_generator.rb +0 -68
  33. data/lib/multi_exiftool/parser.rb +0 -43
  34. data/lib/multi_exiftool/read_object.rb +0 -57
  35. data/script/colorize.rb +0 -6
  36. data/script/generate_fixture.rb +0 -27
  37. data/test/test_command_generator.rb +0 -89
  38. data/test/test_helper.rb +0 -44
  39. data/test/test_parser.rb +0 -51
  40. data/test/test_read_object.rb +0 -36
data/CHANGELOG CHANGED
@@ -1 +1 @@
1
- v0.0.1 experimental
1
+ v0.1.0 First public release.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2009-2010 Jan Friedrich
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/Manifest CHANGED
@@ -1,25 +1,18 @@
1
- Rakefile
1
+ CHANGELOG
2
+ LICENSE
2
3
  Manifest
3
- test/test_command_generator.rb
4
- test/test_helper.rb
5
- test/test_parser.rb
6
- test/test_read_object.rb
7
- lib/multi_exiftool.rb
8
- lib/multi_exiftool/parser.rb
9
- lib/multi_exiftool/command_generator.rb
10
- lib/multi_exiftool/read_object.rb
11
4
  README
12
- data/fixtures/read_non_existing_file.stderr
13
- data/fixtures/read_non_existing_file.stdout
14
- data/fixtures/read_two_files.stderr
15
- data/fixtures/read_one_file.stderr
16
- data/fixtures/read_one_file.stdout
17
- data/fixtures/read_two_files.stdout
18
- data/regression/read_command.rb
19
- data/regression/read_command.rb.out
20
- data/regression/write_command.rb
21
- data/regression/write_command.rb.out
22
- script/generate_fixture.rb
23
- script/colorize.rb
24
- CHANGELOG
25
- COPYING
5
+ Rakefile
6
+ examples/01_simple_reading.rb
7
+ examples/02_simple_writing.rb
8
+ examples/03_reading_using_groups.rb
9
+ lib/multi_exiftool.rb
10
+ lib/multi_exiftool/executable.rb
11
+ lib/multi_exiftool/reader.rb
12
+ lib/multi_exiftool/values.rb
13
+ lib/multi_exiftool/writer.rb
14
+ test/helper.rb
15
+ test/test_reader.rb
16
+ test/test_values.rb
17
+ test/test_values_using_groups.rb
18
+ test/test_writer.rb
data/README CHANGED
@@ -1,29 +1,90 @@
1
- = MULTI EXIFTOOL
2
- Jan Friedrich
3
- http://multi_exiftool.rubyforge.org
1
+ = MultiExiftool
4
2
 
5
- == DESCRIPTION:
3
+ == Description
6
4
 
7
- FIXME (describe your package)
5
+ This library is wrapper for the Exiftool command-line application
6
+ (http://www.sno.phy.queensu.ca/~phil/exiftool) written by Phil Harvey.
7
+ It is designed for dealing with multiple files at once by creating
8
+ commands to call exiftool with various arguments, call it and parsing
9
+ the results.
8
10
 
9
- == FEATURES/PROBLEMS:
11
+ == Examples
10
12
 
11
- * FIXME (list of features or problems)
13
+ === Reading
12
14
 
13
- == SYNOPSIS:
15
+ require 'multi_exiftool'
14
16
 
15
- FIXME (code sample of usage)
17
+ reader = MultiExiftool::Reader.new
18
+ reader.filenames = Dir['*.jpg']
19
+ results = reader.read
20
+ results.each do |values|
21
+ puts "#{values.file_name}: #{values.comment}"
22
+ end
16
23
 
17
- == REQUIREMENTS:
24
+ === Writing
18
25
 
19
- * FIXME (list of requirements)
26
+ require 'multi_exiftool'
27
+
28
+ writer = MultiExiftool::Writer.new
29
+ writer.filenames = Dir['*.jpg']
30
+ writer.values = {creator: 'Jan Friedrich', copyright: 'Public Domain'}
31
+ if writer.write
32
+ puts 'ok'
33
+ else
34
+ puts writer.errors.join
35
+ end
20
36
 
21
- == INSTALL:
37
+ === Further Examples
22
38
 
23
- * FIXME (sudo gem install, anything else)
39
+ See the examples in the examples directory.
24
40
 
25
- == LICENSE:
26
41
 
27
- GNU Lesser General Public License (LGPL)
42
+ == Requirements
43
+
44
+ - Ruby 1.9.1 or higher
45
+ - An installation of the Exiftool command-line application.
46
+ Instructions for installation you can find under
47
+ http://www.sno.phy.queensu.ca/~phil/exiftool/install.html .
48
+
49
+ == Installation
50
+
51
+ First you need Exiftool (see under Requirements above). Then you can simply
52
+ install the gem with
53
+ gem install multi_exiftool
54
+
55
+ == Contribution
56
+
57
+ The code is also hostet in a git repository on Gitorious at
58
+ http://gitorious.org/multi_exiftool
59
+ or
60
+ http://github.com/janfri/multi_exiftool-redesign
61
+ feel free to contribute!
62
+
63
+ == Author
64
+
65
+ Jan Friedrich (janfri26 AT gmail DOT com)
66
+
67
+ == Copyright / License
68
+
69
+ The MIT License
70
+
71
+ Copyright (c) 2009-2010 Jan Friedrich
72
+
73
+ Permission is hereby granted, free of charge, to any person obtaining a copy
74
+ of this software and associated documentation files (the "Software"), to deal
75
+ in the Software without restriction, including without limitation the rights
76
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
77
+ copies of the Software, and to permit persons to whom the Software is
78
+ furnished to do so, subject to the following conditions:
79
+
80
+ The above copyright notice and this permission notice shall be included in
81
+ all copies or substantial portions of the Software.
82
+
83
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
84
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
85
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
86
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
87
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
88
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
89
+ THE SOFTWARE.
28
90
 
29
- See file COPYING.txt for more details.
data/Rakefile CHANGED
@@ -1,43 +1,22 @@
1
1
  require 'echoe'
2
2
 
3
- Echoe.new 'multi_exiftool' do |p|
3
+ Echoe.new('multi_exiftool') do |p|
4
4
  p.author = 'Jan Friedrich'
5
- p.email = 'janfri.rubyforge@gmail.com'
6
- p.project = 'multiexiftool'
7
- p.url = 'http://multiexiftool.rubyforge.org'
8
- p.development_dependencies = ['yact']
9
- end
10
-
11
- namespace :reg do
12
-
13
- ROOT_DIR = File.dirname(__FILE__)
14
- SCRIPT_DIR = File.join(ROOT_DIR, 'script')
15
- DATA_DIR = File.join(ROOT_DIR, %w(data regression))
16
- RB_FILES = File.join(DATA_DIR, '*.rb')
17
-
18
- desc 'Generate regression data'
19
- task :generate
20
-
21
- def target src
22
- src + '.out'
5
+ p.email = 'janfri26@gmail.com'
6
+ p.summary = 'This library is wrapper for the Exiftool command-line application (http://www.sno.phy.queensu.ca/~phil/exiftool).'
7
+ p.description = 'This library is wrapper for the Exiftool command-line application (http://www.sno.phy.queensu.ca/~phil/exiftool) written by Phil Harvey. It is designed for dealing with multiple files at once by creating commands to call exiftool with various arguments, call it and parsing the results.'
8
+ p.ruby_version = '>=1.9.1'
9
+ p.url = 'http://rubyforge.org/projects/multiexiftool'
10
+ p.install_message = %q{
11
+ +-----------------------------------------------------------------------+
12
+ | Please ensure you have installed exiftool version 7.65 or higher and |
13
+ | it's found in your PATH (Try "exiftool -ver" on your commandline). |
14
+ | For more details see |
15
+ | http://www.sno.phy.queensu.ca/~phil/exiftool/install.html |
16
+ +-----------------------------------------------------------------------+
17
+ }
18
+ p.development_dependencies = ['contest']
19
+ p.eval = proc do
20
+ self.requirements << 'exiftool, version 7.65 or higher'
23
21
  end
24
-
25
- FileList[RB_FILES].each do |src|
26
- target = target(src)
27
- file target => src do |t|
28
- sh "ruby #{t.prerequisites.first} > #{t.name}"
29
- end
30
-
31
- task :generate => target
32
- end
33
-
34
- desc 'Running regression tests'
35
- task :test => :generate do
36
- FileList[RB_FILES].each do |src|
37
- target = target(src)
38
- puts '-' * 8 << File.basename(src)
39
- sh "ruby #{src} | wdiff -n #{target} - | #{File.join(SCRIPT_DIR, 'colorize.rb')}"# ; echo x >/dev/null"
40
- end
41
- end
42
-
43
22
  end
@@ -0,0 +1,13 @@
1
+ require 'multi_exiftool'
2
+
3
+ if ARGV.empty?
4
+ $stderr.puts 'No filenames given.'
5
+ exit -1
6
+ end
7
+
8
+ reader = MultiExiftool::Reader.new
9
+ reader.filenames = ARGV
10
+ results = reader.read
11
+ results.each do |values|
12
+ puts "#{values.file_name}: #{values.comment}"
13
+ end
@@ -0,0 +1,19 @@
1
+ require 'multi_exiftool'
2
+
3
+ if ARGV.empty?
4
+ $stderr.puts 'No filenames given.'
5
+ exit -1
6
+ end
7
+
8
+ puts 'Please enter a comment for the given files:'
9
+ comment = $stdin.gets.chomp
10
+
11
+ writer = MultiExiftool::Writer.new
12
+ writer.filenames = ARGV
13
+ writer.overwrite_original = true
14
+ writer.values = {comment: comment}
15
+ if writer.write
16
+ puts 'ok'
17
+ else
18
+ puts writer.errors.join
19
+ end
@@ -0,0 +1,28 @@
1
+ require 'multi_exiftool'
2
+
3
+ if ARGV.empty?
4
+ $stderr.puts 'No filenames given.'
5
+ exit -1
6
+ end
7
+
8
+ reader = MultiExiftool::Reader.new
9
+ reader.filenames = ARGV
10
+ reader.group = 0
11
+ results = reader.read
12
+ results.each do |values|
13
+ # direct access
14
+ puts values.file.filename
15
+ # access via block without parameter
16
+ values.iptc do
17
+ self.keywords do
18
+ puts " Keywords (IPCT): #{Array(self).join(', ')}"
19
+ end
20
+ end
21
+ # access via block with parameter
22
+ values.xmp do |xmp|
23
+ xmp.keywords do |kw|
24
+ puts " Keywords (XMP): #{Array(kw).join(', ')}"
25
+ end
26
+ end
27
+ end
28
+
@@ -1,43 +1,11 @@
1
- require 'multi_exiftool/command_generator'
2
- require 'multi_exiftool/parser'
3
- require 'multi_exiftool/read_object'
4
- require 'open3'
5
- require 'ostruct'
6
- require 'logger'
7
-
8
- # monkey patching --- the save way :D
9
- class OpenStruct
10
- unless self.new.respond_to? :to_hash
11
- def to_hash
12
- @table
13
- end
14
- end
15
- end
1
+ # coding: utf-8
2
+ require_relative 'multi_exiftool/values'
3
+ require_relative 'multi_exiftool/reader'
4
+ require_relative 'multi_exiftool/writer'
16
5
 
17
6
  module MultiExiftool
18
7
 
19
- class << self
20
-
21
- attr_accessor :logger
22
-
23
- def read *filenames
24
- cmd = CommandGenerator.read_command *filenames
25
- stdin, stdout, stderr = Open3.popen3(cmd)
26
- result = Parser.parse(stdout, stderr)
27
- result.map {|r| ReadObject.new(r.data)}
28
- end
29
-
30
-
31
- def write change_set, *filenames
32
- cmd = CommandGenerator.write_command change_set, *filenames
33
- @logger.debug cmd
34
- stdin, stdout, stderr = Open3.popen3(cmd)
35
- result = Parser.parse(stdout, stderr)
36
- result.inject(true) {|r| r.errors.empty?}
37
- end
38
-
39
- end
40
-
41
- @logger = Logger.new nil
8
+ class Error < ::StandardError; end
42
9
 
43
10
  end
11
+
@@ -0,0 +1,67 @@
1
+ # coding: utf-8
2
+ require 'open3'
3
+ require 'shellwords'
4
+
5
+ module MultiExiftool
6
+
7
+ # Mixin for Reader and Writer.
8
+ module Executable
9
+
10
+ attr_accessor :exiftool_command, :errors, :numerical
11
+ attr_writer :options, :filenames
12
+
13
+ def initialize
14
+ @exiftool_command = 'exiftool'
15
+ @options = {}
16
+ end
17
+
18
+ def options
19
+ opts = @options.dup
20
+ opts[:n] = true if @numerical
21
+ opts
22
+ end
23
+
24
+ def filenames
25
+ Array(@filenames)
26
+ end
27
+
28
+ def execute # :nodoc:
29
+ prepare_execution
30
+ execute_command
31
+ parse_results
32
+ end
33
+
34
+ private
35
+
36
+ def escape str
37
+ Shellwords.escape(str)
38
+ end
39
+
40
+ def escaped_filenames
41
+ raise MultiExiftool::Error.new('No filenames.') if filenames.empty?
42
+ @filenames.map { |fn| Shellwords.escape(fn) }
43
+ end
44
+
45
+ def options_args
46
+ opts = options
47
+ return [] if opts.empty?
48
+ opts.map do |opt, val|
49
+ if val == true
50
+ "-#{opt}"
51
+ else
52
+ "-#{opt} #{val}"
53
+ end
54
+ end
55
+ end
56
+
57
+ def prepare_execution
58
+ @errors = []
59
+ end
60
+
61
+ def execute_command
62
+ stdin, @stdout, @stderr = Open3.popen3(command)
63
+ end
64
+
65
+ end
66
+
67
+ end
@@ -0,0 +1,60 @@
1
+ # coding: utf-8
2
+ require_relative 'executable'
3
+ require 'json'
4
+
5
+ module MultiExiftool
6
+
7
+ # Handle reading of metadata via exiftool.
8
+ # Composing the command for the command-line executing it and parsing
9
+ # the results as well as possible errors.
10
+ class Reader
11
+
12
+ MANDATORY_ARGS = %w(-J)
13
+
14
+ attr_accessor :tags, :group
15
+
16
+ include Executable
17
+
18
+ # Options to use with the exiftool command.
19
+ def options
20
+ opts = super
21
+ if @group
22
+ opts["g#{@group}"] = true
23
+ end
24
+ opts
25
+ end
26
+
27
+ # Getting the command for the command-line which would be executed
28
+ # when calling #read. It could be useful for logging, debugging or
29
+ # maybe even for creating a batch-file with exiftool command to be
30
+ # processed.
31
+ def command
32
+ cmd = [exiftool_command]
33
+ cmd << MANDATORY_ARGS
34
+ cmd << options_args
35
+ cmd << tags_args
36
+ cmd << escaped_filenames
37
+ cmd.flatten.join(' ')
38
+ end
39
+
40
+ alias read execute # :nodoc:
41
+
42
+ private
43
+
44
+ def tags_args
45
+ return [] unless @tags
46
+ @tags.map {|tag| "-#{tag}"}
47
+ end
48
+
49
+ def parse_results
50
+ stdout = @stdout.read
51
+ @errors = @stderr.readlines
52
+ json = JSON.parse(stdout)
53
+ json.map {|values| Values.new(values)}
54
+ rescue JSON::ParserError
55
+ return []
56
+ end
57
+
58
+ end
59
+
60
+ end