[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Uppercasing filenames



On Sat, Sep 20, 2003 at 07:34:37PM -0400, Bijan Soleymani wrote:
> On Sat, Sep 20, 2003 at 05:52:44PM -0400, Bijan Soleymani wrote:
> > #!/usr/bin/perl
> > @files=`ls`;
> > foreach $file (@files)
> > {
> >     chomp $file;

Instead of this, it's better to use opendir(), readdir(), and
writedir(). `ls` won't handle files whose names contain spaces, and
while it's convenient it's also IMHO a little inelegant. (Of course,
there's more than one way to do it, and you don't have to choose mine.)

> >     if(-f $file)
> >     {
> > 	$newname = uc $file;
> > 	`mv $file $newname`;
> 
> oops that should be:
> 	`mv "$file" "$newname"`;
> So that files with spaces won't screw up.

That's not reliable either: consider files whose names contain a double
quotation mark. Perl expands those first before the shell sees them, so
the shell can't tell the difference between the quote marks you added
and those in the filename. Also consider files whose names contain a
dollar sign: because you've used double quotation marks the shell may
expand those into environment variable names.

Following are several solutions in increasing order of my preference.

The safest and right way to quote things for the shell in Perl is with
the \Q...\E construct, which can also be spelled as the quotemeta()
function:

  `mv \Q$file\E \Q$newname\E`;

However, you don't need to capture the output of the command, so why use
backquotes? Instead, just use system():

  system("mv \Q$file\E \Q$newname\E");

But there's a better way to call system(), which saves you from having
to worry about these quoting issues at all:

  system('mv', $file, $newname);

Even better yet, you could use the File::Copy module and avoid the shell
altogether:

  use File::Copy;
  move $file, $newname;

And, of course, in all of these cases you should handle errors properly:

  use File::Copy;
  move $file, $newname or die "can't move '$file' to '$newname': $!";

Cheers,

-- 
Colin Watson                                  [cjwatson@flatline.org.uk]



Reply to: