1

I've got a few files named stuff like this: file (2).jpg. I'm writing a little Perl script to rename them, but I get errors due to the brackets not being replaced. So. Can someone tell me how to escape all the brackets (and spaces, if they cause a problem) in a string so I can pass it to a command. The script is below:

#Load all jpgs into an array.
@pix = `ls *.JPG`;

foreach $pix (@pix) {

    #Let you know it's working
    print "Processing photo ".$pix;

    $pix2 = $pix;
    $pix2 =~ \Q$pix\E;    # Problem line

    #Use the program exiv2 to rename the file with timestamp
    system("exiv2 -r %Y_%m%d_%H%M%S $pix2");
}

The error is this:

Can't call method "Q" without a package or object reference at script.sh line [problem line].

This is my first time with regex, so I'm looking for the answers that explain what to do as well as giving an answer. Thanks for any help.

Bojangles
  • 99,427
  • 50
  • 170
  • 208
  • Strings in Perl require quotes. $pix2 = "\Q$pix\E"; – tadmc May 07 '11 at 13:47
  • Silly me. You can tell I have never used Perl before. – Bojangles May 07 '11 at 13:49
  • Notice that you should use `String::ShellQuote` rather than `\Q...\E` to safely escape filenames, see http://stackoverflow.com/q/3796682/23118. – hlovdal Dec 18 '14 at 14:23
  • Although in this case you could avoid the whole need to escape by using system in list mode, `system("exiv2", "-r", "%Y_%m%d_%H%M%S", "$pix");`. – hlovdal Dec 18 '14 at 14:25

2 Answers2

2

Why do not use a simple?

find . -name \*.JPG -exec exiv2 -r "%Y_%m%d_%H%M%S" "{}" \;

Ps: The \Q disabling pattern metacharacters until \E inside the regex.

For example, if you want match a path "../../../somefile.jpg", you can write:

$file =~ m:\Q../../../somefile.jpg\E:;

instead of

$file =~ m:\.\./\.\./\.\./somefile\.jpg:; #e.g. escaping all "dots" what are an metacharacter for regex.
clt60
  • 62,119
  • 17
  • 107
  • 194
1

I found this perl renaming script that was written by Larry Wall a while back... it does what you need and so much more. I keep in in my $PATH, and use it daily...

#!/usr/bin/perl -w

use Getopt::Std;

getopts('ht', \%cliopts);
do_help() if( $cliopts{'h'} );

#
# rename script examples from lwall:
#       pRename.pl 's/\.orig$//' *.orig
#       pRename.pl 'y/A-Z/a-z/ unless /^Make/' *
#       pRename.pl '$_ .= ".bad"' *.f
#       pRename.pl 'print "$_: "; s/foo/bar/ if <stdin> =~ /^y/i' *

$op = shift;
for (@ARGV) {
   $was = $_;
   eval $op;
   die $@ if $@;
   unless( $was eq $_ ) {
      if( $cliopts{'t'} ) {
         print "mv $was $_\n";
      } else {
         rename($was,$_) || warn "Cannot rename $was to $_: $!\n";
      }
   }
}

sub do_help {
   my $help = qq{
   Usage examples for the rename script example from Larry Wall:
        pRename.pl 's/\.orig\$//' *.orig
        pRename.pl 'y/A-Z/a-z/ unless /^Make/' *
        pRename.pl '\$_ .= ".bad"' *.f
        pRename.pl 'print "\$_: "; s/foo/bar/ if <stdin> =~ /^y/i' *

   CLI Options:
   -h      This help page
   -t      Test only, do not move the files
      };
   die "$help\n";
   return 0;
}
Mike Pennington
  • 41,899
  • 19
  • 136
  • 174
  • Thanks for your help Mike, but I got it by myself - `quotemeta()` works wonders. This script looks good, but doesn't suit my needs. +1 for effort though :-) – Bojangles May 07 '11 at 12:27
  • You could post your own answer and accept it if you like... that would also get you a measley 2 points :) – Mike Pennington May 07 '11 at 12:33
  • 1
    Not even sneaky... in fact, it is [encouraged](http://meta.stackexchange.com/questions/89333/whats-the-best-way-to-post-a-tutorial-on-so/89339#89339) – Mike Pennington May 07 '11 at 14:15