http://www.perlmonks.org?node_id=345472

It is common knowledge that module names are case-sensitive. This makes sense, because package names are case-sensitive.

It is also widely known that modules are stored in a directory structure that mirrors their names, such that Beverage::Carbonated::CO2 is stored in lib/Beverage/Carbonated/CO2.pm.

It is less widely known that some file systems are case-insensitive, notably those used by the MacOS (including MacOS X) and some configurations of Windows.

The result of these three facts is that Beverage::Carbonated::CO2 and Beverage::Carbonated::Co2 are different modules, with different packages, but cannot be easily installed at the same time on some OSes.

"So what?" you ask. "Surely there aren't any CPAN modules whose names differ only in capitalization!"

Unfortunately, there are.

As of 12 April 2004, 44 sets of CPAN modules had names that differed only in capitalization. The full list appears at the end of my post, along with the program that generated it.

I first realized this problem when I was checking to see if I had the latest version of Pod::HTML. Um, I mean, Pod::Html. The latter is included with the core Perl distribution, the former is part of the PodSimplify distribution. The problem is, the two are different modules, with different interfaces. If I had actually installed Pod::HTML, it would have overwritten Pod::Html, meaning that pod2html and any script that used Pod::Html would no longer work, and I would have a heck of a time figuring out why.

The lesson is, make sure your module's name differs from other modules' names in more than just capitalization, and be careful about capitalization when you're installing a module on a case-insensitive file system.

perlport says:

Do not have two files or directories of the same name with different case, like test.pl and Test.pl, as many platforms have case-insensitive (or at least case-forgiving) filenames.
It might be a good idea to add something about module names after that.

Please note that this is not a flame against anyone who has written a module whose name differs from another module's by only case. It's difficult to take into account the peculiarities of other platforms when you're developing, especially when you can't test on those platforms.

(And yes, I am aware that there can be several different lib directories in which modules can be installed, but as long as one of them is always used for module installation, the problem with overwriting modules still applies.)

The list of modules and the program used to generate the list appear below:

44 sets of duplicates:
  • Apache::Test | Apache::test
  • base | Base
  • Bio::Das::Request::dsn | Bio::Das::Request::Dsn
  • Bio::SeqIO::EMBL | Bio::SeqIO::embl
  • Bio::SeqIO::Fasta | Bio::SeqIO::fasta
  • Bio::SeqIO::GCG | Bio::SeqIO::gcg
  • Bio::SeqIO::Raw | Bio::SeqIO::raw
  • Class::PObject::Driver::DB_File | Class::PObject::Driver::db_file
  • Crypt::SecurID | Crypt::securid
  • Crypt::TEA | Crypt::Tea
  • DES | Des
  • example | Example
  • Example1 | example1
  • FAQ::OMatic::Help | FAQ::OMatic::help
  • FAQ::OMatic::Search | FAQ::OMatic::search
  • File::Stat | File::stat
  • Finance::Shares::Momentum | Finance::Shares::momentum
  • Foo | FOO
  • Gettext | gettext
  • Graphics::PLPLOT | Graphics::PLplot
  • Inline::CPP::Grammar | Inline::CPP::grammar
  • LISP::List | Lisp::List
  • LWP::Authen::Basic | LWP::Authen::basic
  • LWP::Authen::Digest | LWP::Authen::digest
  • Math::GSL | Math::Gsl
  • Mcrypt | MCrypt
  • MP3::Tag::ID3v1 | MP3::TAG::ID3v1
  • MP3::Tag::ID3v2 | MP3::TAG::ID3v2
  • My::db | My::DB
  • Net::LDAP::Control::Sort | Net::LDAP::Control::sort
  • Net::TrackBack | Net::Trackback
  • Petal::Hash::VAR | Petal::Hash::Var
  • Pod::HTML | Pod::Html
  • Pod::Rtf | Pod::RTF
  • pragmatic | Pragmatic
  • Qt | QT
  • SGI::syssgi | SGI::Syssgi
  • stem | Stem
  • swig | SWIG
  • Sys::Lastlog | SYS::lastlog
  • testcases::Base | testcases::base
  • types | Types
  • URI | uri
  • XBase | Xbase
The above was generated with this program:
#!/usr/bin/perl -w use strict; #File below is decompressed http://perl.org/CPAN/modules/02packages.de +tails.txt.gz open(MODULES, '<', '02packages.details.txt') or die "Can't open module + info: $!"; my %all_modules; my %duplicates; my $inheader = 1; #02packages.details.txt has several header lines, th +en a blank line, then the module names. while (<MODULES>) { if ($inheader) #This technique for ignoring the header was taken f +rom { #Merlyn's MINICPAN script: http://www +.stonehenge.com/merlyn/LinuxMag/col42.html $inheader = 0 unless /\S/; next; } my ($module, undef, undef ) = split; if(exists $all_modules{lc $module}) { push @{$all_modules{lc $module}}, $module; $duplicates{lc $module} = 1; } else { $all_modules{lc $module} = [$module]; } } print scalar(keys %duplicates)." sets of duplicates:\n\n"; foreach(sort keys %duplicates) { print join ' | ', @{$all_modules{$_}}; print "\n"; }

Once it's Turing complete, everything else is just syntactic sugar.