Don’t forget that path!

I wanted to rename some files, so I pulled out File::Find and created a callback to do that. Then nothing appeared to happen:


use utf8;
use File::Find;

my $wanted = sub {
	rename $_ => q(Côte_d'Ivoire.png) if /Ivoire/;
	};

find( $wanted, @ARGV );

But, this doesn’t work! The value in $_ is just the filename, so unless that file is in the current working directory, my files aren’t renamed:

use utf8;
use File::Find;

my $wanted = sub {
	rename $File::Find::name => q(Côte_d'Ivoire.png) if /Ivoire/;
	};

find( $wanted, @ARGV );

This doesn’t work, and I know it doesn’t work because I’ve made the same mistake before. And before that. And many times before that.

Fortunately for me, all of this was in a git repository, so I discard that changes and start again.

% git checkout -- .

The problem is one of paths. $File::Find::name has the full path to a file. The callback gets just the filename in $_, which is why I can use that for the regex target with a false match from some other path portion. However, when I do the rename, I take the path and move it to a file in the current directory. All files collapse into the same file and whoever gets there last wins.

I have to be more careful. I get the directory name and prepend it to the new file name:

use utf8;
use File::Basename qw(dirname);
use File::Spec::Functions;

my $wanted = sub {
	next unless /Ivoire/;
	my $dirname = dirname( $File::Find::name );
	rename $File::Find::name => catfile( $dirname, q(Côte_d'Ivoire.png) );
	};

This is also a problem with opendir, which only returns the filename, unlike glob.

Leave a comment

0 Comments.

Leave a Reply

You must be logged in to post a comment.