From the Exiftool website[http://www.sno.phy.queensu.ca/~phil/exiftool]: ''ExifTool is a platform-independent Perl library plus a command-line application for reading, writing and editing meta information in a wide variety of files.'' The command-line has a large variety of options to do various things to one file or many. I ([EMJ]) use ExifTool a lot with my photo collection, adding metadata as well retrieving it for a variety of purposes. Doing the same thing with lots of files is easy and efficient, but doing the same sort of updates but with different values to a lot of files can be very slow, needing many invocations of the program. Howver, ExifTool provides for this (again from the website): ''... the `-execute` option may be used to perform multiple independent operations with a single invocation of exiftool, and together with the `-stay_open` option provides a method for calling applications to avoid (the) startup overhead'' Add this to ''-@ ARGFILE'': ''Read command-line arguments from the specified file. The file contains one argument per line (NOT one option per line -- some options require additional arguments, and all arguments must be placed on separate lines). Blank lines and lines beginning with `#` and are ignored. Normal shell processing of arguments is not performed, which among other things means that arguments should not be quoted and spaces are treated as any other character. ARGFILE may exist relative to either the current directory or the exiftool directory unless an absolute pathname is given.'' (which doesn't mention '''-@ -''' for '''stdin''') and you have something that can easily be driven from Tcl using [open] (as `open |`) and [fileevent]. After a fair bit of messing about, I have ended up with the following: ====== #!/usr/bin/tclsh #--------------------------------------------------------------------------- # start of "package" # namespace eval ::run_exiftool { variable et_vars set et_vars [dict create] # the caller can use this dict, we only care about the keys "chan" and # "func" } # called by the user to start using ExifTool proc ::run_exiftool::start { func } { variable et_vars # remember the user-supplied function dict set et_vars func $func # start ExifTool in the right way and remember the channel for the pipe set et [open "|exiftool -stay_open true -@ -" r+] fconfigure $et -blocking false fileevent $et readable [list [namespace current]::isReadable] dict set et_vars chan $et # call the user-supplied function with the NAME of the dictionary and the # special string "INIT" $func [namespace current]::et_vars INIT # presumably the user-supplied code will feed arguments to ExifTool, # deal with its output and, eventually, stop it properly. vwait ::DONE close [dict get $et_vars chan] } # this is how to stop ExifTool properly proc ::run_exiftool::stop {} { variable et_vars set et [dict get $et_vars chan] puts $et "-stay_open" puts $et "false" flush $et } # pretty much a standard fileevent handler proc ::run_exiftool::isReadable {} { variable et_vars set et [dict get $et_vars chan] # The channel is readable; try to read it. set status [catch { gets $et line } result] if { $status != 0 } { # Error on the channel puts "error reading $et: $result" set ::DONE 2 } elseif { $result >= 0 } { # Successfully read the channel, so tell the user (dict passed # by NAME) set usr_status [catch { [dict get $et_vars func] [namespace current]::et_vars $line } usr_result] if { $usr_status != 0 } { puts "error in user function: $usr_result" close $et set ::DONE 99 } } elseif { [eof $et] } { # End of file on the channel set ::DONE 1 } elseif { [fblocked $et] } { # Read blocked. Just return } else { # Something else puts "can't happen" set ::DONE 3 } } # end of "package" #--------------------------------------------------------------------------- ====== Not actually a package yet, of course. When everthing is ready, we will want to do ====== # ::run_exiftool::start do_one_line ====== so here is a suitable proc: ====== proc do_one_line { et_dict line } { } ====== To be continued ... <> Image Processing | Interprocess Communication