Simple Filename Parsing Question
March 9, 2008 7:33 AM   Subscribe

Should-be-simple Linux timestamped file parsing question.

I have a directory with what is now 10k jpeg files in this format (number of seconds since 1970):

1202499302.jpg
1202419201.jpg
1202439301.jpg
1202459401.jpg
1202479501.jpg
1202499602.jpg
1202419502.jpg
1202439601.jpg
1202459702.jpg
1202479801.jpg
1202499901.jpg

I'd like to use a script of some sort to shuffle these images into directories based on month, then day. Note that the "last modified" times on the file system are not necessarily the same as the timestamp in the file name, and I'd like to collate the files with the file name timestamp, not the filesystem timestamp.

Can anyone suggest a way to do this?
posted by yellowbkpk to Computers & Internet (7 answers total) 3 users marked this as a favorite
 
you can totally do this easy with python. the functions you want to look at are all in the os builtin libraries: os.listdir, os.makedirs, and os.renames.
posted by Mach5 at 8:17 AM on March 9, 2008


Best answer: Run this Perl script with one argument, the path to the directory containing the JPG files. This version just prints the actions it would take. If you're satisfied with what you see, change the print calls to system calls and it will move the files for real.
#!/usr/bin/perl                                                                                                                                                 use File::Basename;                                                                                                                                             my $dirname = $ARGV[0];                                                         opendir(DIR, $dirname) or die "Couldn't open directory $dir: $!";                                                                                               my $file;                                                                       while (defined($file = readdir(DIR))) {                                             my $basename = basename($file, ".jpg");                                         if ($basename !~ /[^0-9]/) {                                                        my ($sec, $min, $hrs, $day, $mon, $year, $wday, $yday, $dst) = localtime($basename);        my $datetime = localtime($basename);                                            my $realyear = $year + 1900;                                                    my $targetdir = "$dirname/$realyear/$mon/$day";                                 print("mkdir -p $targetdir\n");                                                 print("mv $dirname/$file $targetdir/$basename.jpg\n");                      }                                                                           }                                                                                                                                                               closedir(DIR);

posted by letourneau at 8:29 AM on March 9, 2008


Never mind the spurious line my $datetime = localtime($basename); in there, I was trying something that didn't work. That's a leftover I forgot to delete before posting; you can delete it and the script will run exactly the same without it.
posted by letourneau at 8:31 AM on March 9, 2008


Ugh, and when you change the print calls to system calls, remove the \n's from the lines. Every time I post code to MetaFilter, I immediately find a half-dozen little nits I forgot to pick. Sheesh!
posted by letourneau at 8:39 AM on March 9, 2008


Response by poster: Thanks go to both of you -- the perl code worked wonderfully.
posted by yellowbkpk at 9:21 AM on March 9, 2008


Take letourneau's script, and rather than edit it to s/print/system/, run it once to view, and if you like what you see, run it again and pipe into "sh -x" to execute what it says.

This is really handy as you can intermix commands and comments in your program output.
posted by devbrain at 10:17 AM on March 9, 2008 [1 favorite]


Best answer: You can do it this way in one line of shell:

for f in *.jpg; do t=${f%.jpg}; d=$(date -d @$t +%Y/%m/%d); echo "mkdir -p $d && mv $f $d/$f"; done

Note this won't work on OS X - you'd need to substitute "-r $t" for "-d @$t".
posted by sergent at 2:01 PM on March 9, 2008 [2 favorites]


« Older Dobro n00b seeks advice   |   How can I best thank a whole hospital, but still... Newer »
This thread is closed to new comments.