Path::Class and File::Copy (perl-5.10)

Chisel Wright chisel at
Tue Aug 26 10:40:59 BST 2008

I foolishly extended the test suite for one of my modules last week;
after fixing stupid omissions I started getting Failed Test reports.

They're all from 5.10.0 and are of the form:

  Argument "/some/file" isn't numeric in numeric
  eq (==) at /path/tolib/5.10.0/File/ line 70.

After installing 5.10.0 I tracked this down to File::Copy::_eq() and
Path::Class objects.

 sub _eq {
   return $_[0] == $_[1] if ref $_[0] && ref $_[1];
   return $_[0] eq $_[1] if !ref $_[0] && !ref $_[1];
   return "";

The problem is down to ref($_[x]) being a Path::Class::File, causing the
"==" comparison to be made ... using $_[x] in scalar context causing it
to stringify.

I've solved the problem locally by making my call look like:

  	file($dir1, $file1) . q{},
  	file($dir2, $file2) . q{},

But it just feels wrong and icky.

What are people's thoughts on the best way to resolve this going
Should I stick with my ".q{}" solution?
Should _eq() be extended to handle the passing of something like a
Path::Class::File object?
I don't think Path::Class itself is doing anything "wrong" - it
stringifies when I expect it to usually.

Here's a script that demonstrates the issue for the curious/interested -
remember it'll only fail with the newer File::Copy from 5.10.0

---- t/01.path-class.t ----
#!/usr/bin/env perl
# vim: ts=8 sts=4 et sw=4 sr sta
use strict;
use warnings;
use Test::More tests => 11;

# show the verson of perl we're running the tests as
diag sprintf "version is v%vd\n", $^V;

use_ok 'File::Copy';
use_ok 'File::Temp', qw(tempfile tempdir);
use_ok 'IO::File';
use_ok 'Path::Class';

# create a temporary directory
my $dir = tempdir( CLEANUP => 1 );

# get names for our two files
my $file1 = file($dir,q{file1});
my $file2 = file($dir,q{file2});
# make sure they're the objects we expect
isa_ok($file1, 'Path::Class::File');
isa_ok($file2, 'Path::Class::File');
# a couple of like() tests for stringification confirmation
like($file1, qr{file1$}, q{$file1 name is like 'file1'});
like($file2, qr{file2$}, q{$file2 name is like 'file2'});

# make a tempfile
my $fh = new IO::File $file1, "w";
if (defined $fh) {
    print $fh "bar\n";
# check it exists
ok (-f $file1, q{source file exists});
# check the destination file does not exist
ok (! -f $file2, q{destination does not exist yet});

# now copy file1 to file2
copy($file1, $file2);

# the destination file _should_ exist now
ok (-f $file2, q{destination file exists});

# this is the offending method from /opt/perl/lib/5.10.0/File/
# sub _eq {
#   return $_[0] == $_[1] if ref $_[0] && ref $_[1];
#   return $_[0] eq $_[1] if !ref $_[0] && !ref $_[1];
#   return "";
# }
#diag _eq($file1, $file2);
---- t/01.path-class.t ----

Chisel Wright
e: chisel at

  I may be a pretty sad person, but I don't make jokes in base 13.

More information about the mailing list