Beginner am Freitag, 24. November 2006 14:48:
> Hi,
>
> I have a number of jpegs I wanted to rename. I wrote a short script
> to do it but the new file name is not always generated correctly. The
> script should find the last letter in the filename (before the
> extension) and substitute it for '_a'.

Hi Beginner

I assume that you mean "substitue with _a".

> If you look at the results below you'll see that 'a' and 'b' fail but
> 'c' worked. I don't understand why.
>
> DSC00092a.jpg -> DSC00092a.jpg a
> DSC00093b.jpg -> DSC00093b.jpg b
> DSC00094c.jpg -> DSC00094_a.jpg c
> DSC00095d.jpg -> DSC00095d.jpg d
> DSC00096e.jpg -> DSC00096e.jpg e
> DSC00097f.jpg -> DSC00097f.jpg f
> DSC00098g.jpg -> DSC00098g.jpg g
> DSC00099h.jpg -> DSC00099h.jpg h
> DSC00100i.jpg -> DSC00100i.jpg i
> DSC00101j.jpg -> DSC00101_a.jpg j
> DSC00102k.jpg -> DSC00102_a.jpg k
> DSC00103l.jpg -> DSC00103l.jpg l
> ...snip
>
> Here the script, there isn't much to it. Can anyone explain why the
> substitute fails?

I should not mention that in the public ;-) but, just to demonstrate one way 
to search for a reason for a malfunction:

Because I did not see an error at first glance, I...

> #!/bin/perl
> # Active State 5.8.6.811
>
> use strict;
> use warnings;
> use File::Basename;
>
> my $dir = 'D:/Temp/jpegs/thumbs/';
> my @files = glob("${dir}*.jpg");

...replaced these two lines with simply 

   my @files=qw(DSC00092a.jpg DSC00094c.jpg); # etc

and everything worked fine. 
   Then, I created these files in the current directory, and again everything 
worked fine.

Then, I made a subdirectory, moved the file over, ...


> foreach my $f (@files) {
>       (my $l) = ($f =~ /([a-z]|[a-z][a-z])\.jpg/);
>       (my $new = $f) =~ s/$l/_a/;

...placed here a 

   warn "new=$new";

and got (excerpt):

new=/home/d_ani/ramsch/thumbs/DSC00092a.jpg at ./script.pl line 17. # !!
new=/home/dani/ramsch/thum_as/DSC00093b.jpg at ./script.pl line 17. # !!
new=/home/dani/rams_ah/thumbs/DSC00094c.jpg at ./script.pl line 17. # !!
new=/home/dan_a/ramsch/thumbs/DSC00100i.jpg at ./script.pl line 17. # !!
new=/home/dani/ramsch/thumbs/DSC00101_a.jpg at ./script.pl line 17.

>       my $basef = basename($f);
>       my $basenew = basename($new);
>       print "$basef -> $basenew $l\n";
> }

And now it's extraordinary obvious that the error is

  (my $new = $f) =~ s/$l/_a/;

which simply searches for the first char contained in $l and replaces it 
with '_a'. This makes the malfunction dependent from the contents in $dir.

Instead, this line should be more specific, f.ex:

  (my $new = $f) =~ s/$l\.jpg$/_a\.jpg/;

(Note that I anchor with $ since "DSC00092a.jpg" is a valid path name :-) )

Of course it would have been sufficient to only present this last substitution 
to lead you to a "aha!", but I think it's important to have a personal 
strategy to search for errors in the dark :-)


btw, the foreach code can at least be shortened to:

foreach my $basef (map basename ($_),  @files) {
  (my $l) = ($basef =~ /([a-z]{1,2})\.jpg$/);
  # above line is still problematic: What if the match failes?

  (my $basenew = $basef) =~ s/$l\.jpg$/_a\.jpg/;
  print "$basef -> $basenew $l\n";
}

and certainly optimized further in several ways (f.ex if you don't need the 
last print statement, $l could possibly be eliminated), but I'm so tired and 
brain dead at the time :-)

Dani

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to