coolboarderguy has asked for the wisdom of the Perl Monks concerning the following question:

Hi All,

am wishing to change a particular extension of files in a particular directory with the code below,

#!/usr/bin/perl use strict; use warnings; use File::Find; my $dir = shift; find(\&change_ext_if_file, "$dir"); sub change_ext_if_file { foreach my $file ($_) { if (($file eq -f) && ($file =~ /.pdf$/)) { $file =~ s/.pdf$/.doc/; } } }

but, no changes eventuate. Obviously missing something fundamental? Is it the below line,

foreach my $file ($_) {

or

$file =~ s/.pdf$/.doc/;

Cheers

coolboarderguy.

Replies are listed 'Best First'.
Re: No Substitution Happening
by Corion (Patriarch) on Mar 24, 2006 at 07:34 UTC

    You change the string, but don't rename the file. You could have debugged that further to see if your substitution on the filename actually happens, and have printed that out. print is a very good mechanism to see what happens in your program.

    On an aside, $file eq -f likely doesn't do what you want. If you want to check if a file exists under a certain name, use -f $file.

Re: No Substitution Happening
by GrandFather (Saint) on Mar 24, 2006 at 07:41 UTC

    $dir doesn't need to be interpolated into a string, it is already.

    $_ doesn't have any useful contents inside the sub and it certinally isn't an array, or even a reference to and array, so foreach doesn't help anything.

    Chaning the contents of the variable $file would only help if you were itterating over array elements in the foreac, but you've not got an array to itterate over.

    The following code may get you headed in the right direction:

    use strict; use warnings; use File::Find; my $dir = shift; find(\&change_ext_if_file, $dir); sub change_ext_if_file { my $file= $File::Find::fullname; return if -d $file; # skip directories return if $file !~ /\.pdf/i; # Ignore anything that's not a .pdf (my $newName = $file) =~ s/pdf$/doc/i; #do whatever needs to be done with the new filename - rename maybe +? #rename $file, $newName; }

    DWIM is Perl's answer to Gödel
      Hi All,

      $dir doesn't need to be interpolated into a string, it is already.

      Could you elaborate a little on that, please? Are you referring to the foreach of $dir?

      $_ doesn't have any useful contents inside the sub and it certinally isn't an array, or even a reference to and array, so foreach doesn't help anything.

      Does the below make it into an array?

      sub change_ext_if_file { @files = $_; #continuing code left off for this post

      Cheers

      coolboarderguy...

        When you use a variable inside a string like "This is a string with $var interpolated into it" Perl replaces the variable ($var in this example) with the contents of the variable. However, if you write "$var" you can omit the quotes because the variable will generally be treated as a string in any case.

        A variable that starts with $ is a scalar variable. They can only store one thing, a number or a string or a reference to something. $_ is just a special scalar variable that is used by default for some things. At the start of a subroutine you generally should not depend on $_ being set to some expected value. You need to ask yourself "Where is $_ getting a value from and what sort of value is it?". To answer that you need to look at the documentation for, in this case File::Find, and see if it says that $_ is getting set to some value for you. If it doesn't (it doesn't you know), then it ain't.

        It may be that you are getting confused with @_, which is the special array variable used to pass parameters into a subroutine. However, again you need to consult the documentation to see what is passed into the subroutine by File::Find. From the documentation you will find that "The wanted function takes no arguments but rather does its work through a collection of variables.". So that doesn't help you either.

        Take another look at the code that I wrote and search the File::Find documentation for anything that looks File::Find related that you don't understand. Everything else should be pretty clear. :)


        DWIM is Perl's answer to Gödel
        Hi All,

        please see the below code,

        #sub change_ext_if_file { #foreach my $file ($_) { # if (($file eq -f) && ($file =~ /.pdf$/)) { # $file =~ s/.pdf/.doc/; #Above, better written as below, perhaps? sub change_ext_if_file { my @files = $_; foreach my $file if ((@files eq -f) && (@files =~ /\.pdf$/)) { $file =~ s/pdf/doc/; } }

        I'm guessing, going by some code suggestions above, that there is a quicker, cleaner way of achieving the end result, but, I'm just playing, to learn what things do, so I'm not looking, I guess, for shorter ways just yet. Hope that makes sense, and doesn't seem ungrateful? Cheers

        coolboarderguy...