tags:

views:

1325

answers:

4

Given the following file/directory structure:

/photos/1/original/filename1.jpg
/photos/1/thumb/filename1.jpg
/photos/2/original/filename2.jpg
/photos/2/thumb/filename2.jpg
/photos/3/original/filename3.jpg
/photos/3/thumb/filename3.jpg

...etc. I'm looking for the regexp to convert the file/directory structure to:

/photos/1/original.jpg
/photos/1/thumb.jpg
/photos/2/original.jpg
/photos/2/thumb.jpg
/photos/3/original.jpg
/photos/3/thumb.jpg

...etc. I've got scripts to do the file renaming in ruby or perl...just missing the proper regexp.

Thanks for any help in advance!

+2  A: 

Perl solution

$newfn = $oldfn;
$newfn =~ s/(original|thumb)[^\.]*/$1/;
rename($oldfn, $newfn);

As requested, to match any keyword, not just "original" or "thumb", assuming that the /photos/nn remains the same:

$newfn = $oldfn;
$newfn =~ s?(photos/\d+/[^/]*)/[^\.]*?$1?;
rename($oldfn, $newfn);

Adapting this solution to also remove the directories if they are empty

$newfn = $oldfn;
$newfn =~ s?(/photos/\d+/)([^/]*)/[^\.]*?$1$2?;
rename($oldfn, $newfn);
unlink($1$2);

I'm not sure what this will do if the directory is not empty when you go to unlink it.

Paul Tomblin
Would you be able to offer a more generic solution? So, if say there were more folder names than just thumb or original, would it be possible to change your exp to account for any x folder names? Thanks Paul.
Mike
Does that do the job in the first place?
Jonathan Leffler
Actually, no. Now that I've tested it, it doesn't seem to do anything...
Mike
Well, you have to actually move the file afterwards - I was just giving you the regexp to generate the new file name.
Paul Tomblin
This could be achieved by evaluating "rename($oldfn, $newfn);" correct? If so, I'm not sure what I'm missing.
Mike
Working now, thanks Paul. How about cleanup? i.e. removing the old folders?
Mike
I left out a "*". That's why it wasn't working when you tested it.
Paul Tomblin
Great, thanks for your help Paul.
Mike
+1  A: 

Adapting Paul Tomblin's solution and providing the more generic renaming:

my $newfn = $oldfn;
$newfn =~ s%(/\d+/[^/]+)/[^/]+(\.[^./]+)$%$1$2%;

Let's expand that with the 'x' option:

$newfn =~ s%
                (              # start remembering
                /\d+/          # /397/
                [^/]+          # original, thumb, othername, ...
                )              # stop remembering
                /              # directory
                [^/]+          # filename within directory
                (\.[^./]+)$    # remember extension matching to end of name
           %
                $1$2           # /397/original.png
           %x;

(Untested - there could be typos.)

Jonathan Leffler
A: 

Here is a ruby solution:

require 'fileutils'

old_file = "/photos/1/original/filename1.jpg"
new_file = old_file.sub(/(\d+)\/(\w+)\/.+(\.\w+)/, '\1/\2\3')
FileUtils.mv(old_file, new_file)
nan
A: 

Note: While this doesn't directly answer your question, I think you'll still find this useful. Linux and cygwin both have commands "rename" and "mmv" (multiple move), which can meet this need. Given your directory structure and your request, you can trivially use the rename command to solve this problem:

cd /photos/1/original
rename filename original *.jpg
mv *.jpg ..
cd ../thumb
rename filename thumb *.jpg
mv *.jpg ..
cd ../2
  .... (repeat for other directories)

You'll have to check the man page for mmv, but it looks like you can do something like (this is untested):

cd /photos
mmv "*/original/filename*.jpg" "./#1/original#2.jpg"
mmv "*/thumb/filename*.jpg" "./#1/thumb#2.jpg"

and this will both rename the file and move the file into the desired directory for the whole tree of files that you wish to handle. The double-quotes are mandatory.

Eddie