Preamble: I hate to ask questions like this, but I'm stuck with it and just learning Perl... seems like an easy task but I don't know where to look.
I have a folder with lots of xml-files that are all named ".xml". I need to process those files in their numeric order, so "9123.xml" should come before "2384747.xml". I have successfully sorted the list alphabetically with this:
opendir(XMLDIR,$xmldirname);
my @files = sort {$a cmp $b} readdir(XMLDIR);
but this isn't what I need.
I also tried
my @files = sort {$a <=> $b} readdir(XMLDIR);
which obviously fails because the filenames contain ".xml" and are not numeric as a whole.
Could someone open their heart and save me a week of browsing the Perl manuals?
The problem is that
<=>
cannot work on something that is not entirely a number, in fact if youuse warnings;
you would get a message similar to this at run-time:What you can do is separate out the filename from the extension, sort numerically on the filename then re-combine the extensions in. This can be done fairly straightforward with a
Schwartzian transform
:Or without the temporary variables:
You are actually pretty close. Just strip off the ".xml" when inside your compare:
Despite your claim,
sort { $a <=> $b } readdir(XMLDIR)
works. When Perl treats the string2384747.xml
as a number (as<=>
does), it is treated as having the value2384747
.Of course, those warnings are a problem. The solution you accepted tries to remove them, but fails to remove all of them because it doesn't take into account that
readdir
will return.
and..
. You gotta remove the files you don't want first.Here are two simple solutions:
In this particular case, you can optimize your code:
The simplest and fastest solution, however is to use a natural sort.