Re: sort files by exif date



Chris Ellison <cjellison@xxxxxxxxxxx> wrote:
>jpd wrote the following on 2005-12-31 14:35:
>> Then I'd probably have a script take a
>> list of filenames, extract the required data from the files and put it
>> and the filenames in a list, sort, then extract the filenames again.
>> Probably a few lines of shell script. It does require having the files
>> on hand to extract the required extra data from.
>>
>
>That's exactly what I figured I'd need to do, but I really don't
>know how to do that. I'm new to perl...so I need a lot of help.

Perl? What for? :-)

>jhead is the tool I'd use to extract the exif data. Can someone
>cook up a quick script (with some comments) that does something
>like what jpd described. I can learn from that and adjust it to
>do exactly what I need.

Here are the basics of what you want, though I can't determine
precisely what format you need. If you have trouble figuring
out how to adjust this to your needs, just ask... and give an
example of what you want the output to look like.

#!/bin/bash
#
# Output a sorted list of JPEG files, ordered by
# the exif date/time stamp.
#
for i in *.jpg ; do
date=$(jhead ${i} | grep "^Date/Time :")
set ${date}
echo "${3}-${4} ${i}"
done | sort

Here is an example of the results:

>./foo
2005:12:31-01:00:00 c.jpg
2005:12:31-02:00:00 b.jpg
2005:12:31-02:01:00 a.jpg
2006:01:01-00:01:00 f.jpg
2006:01:01-10:01:00 e.jpg
2006:01:01-10:01:01 d.jpg
2006:01:01-10:01:02 g.jpg

Where, for example, jhead outputs this type of
information for one of the files:

>jhead e.jpg
File name : e.jpg
File size : 1153380 bytes
File date : 2006:01:01 10:05:43
Camera make : NIKON CORPORATION
Camera model : NIKON D1
Date/Time : 2006:01:01 10:01:00
...


Specifically, line by line what the script does is:

for i in *.jpg ; do

First we have a loop that looks at all files in this directory
ending in ".jpg". (This could be made much more sophisticated,
for example by using a command line parameter to look in any
specific directory).

set $(jhead ${i} | grep "^Date/Time :")

That runs the command /jhead/ on each file selected, and output
is piped to the /grep/ command which selects only lines with the
pattern specified. The pattern I used has only one thing other
than just plain ASCII text, and that is the '^' character at the
beginning to specify the text must be at the beginning of a line
to be selected. The output from jhead piped to grep is then
interpreted as a string because it is enclosed in $(...).

That string will be a line of text. For the file named e.jpg in
the example shown above, the line of text will look like this:
"Date/Time : 2006:01:01 10:01:00"

That string is the argument for /set/, which tokenizes the
string and makes each word available as a positional parameter,
$1 through $9.

We don't care about "Date/Time" in $1, or ":" in $2, but I
wanted the "2006:01:01" in $3 and "10:01:00" in $4 to be a
single word with no spaces, hence the below line is used to
output the text from each iteration of the loop:

echo "${3}-${4} ${i}"

That gives a line formatted as: "2006:01:01-10:01:00 e.jpg"

done | sort

And that line sends the entire output of the loop to the /sort/
program, which prints it to the screen as an alphabetically sorted
list.

Note that the sorting was made easy by putting the date/time stamp
at the beginning of each line. A different format might require
complex trickery with /sort/ parameters to get both the sort
and the format right. Buyt it is also possible to use /cut/ to
eliminate whatever is used at the beginning of the line as the
key for /sort/ too. For example, here's a variation you might
use:

done | sort | cut -d\ -f2

Only the file name will be output, not the date. Or with

echo "${3}-${4} ${i} ${3} ${4}"
done | sort | cut -d\ -f2-4

The output looks like this:

e.jpg 2006:01:01 10:01:00

--
Floyd L. Davidson <http://www.apaflo.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) floyd@xxxxxxxxxx
.



Relevant Pages