Since you've used a bareword directory handle, you clobber your existing handle every time you descend a level. Never use bareword handles for recursive calls. Problem solved if you use a lexical/indirect handle:
use strict;
use warnings;
use Cwd 'getcwd';
## cwd
my $cwd = getcwd;
## Get files from cwd
my $res = _list_files($cwd);
sub _list_files {
my $dir = shift;
my $files = shift;
opendir(my $dh, $dir) || die "Error opening: $dir\n";
while (my $fn = readdir($dh)) {
## skip hidden
next if $fn =~ /^\./;
## file, fullpath name
my $file = $dir . "/" . $fn;
## add
push(@{ $files }, $file);
## dir, decend
if (-d $file) {
## sub-directory files
$files = _list_files($file, $files);
}
}
#closedir($dh); # Not necessary; auto-closed on end of scope
return $files;
}
See also
How do I traverse a directory tree?
#11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.