use File::Find;
use File::Basename;
@ARGV = qw(directorio) unless @ARGV; # directorio del que partimos
map { s|\\|/|g; $_ .= "/" unless (m|/$|) } @ARGV; # A todos los directorios a procesar
# le agregamos un '/' al final, si no lo tiene ya, y
# cambiamos los '\' por '/'
@ARGV = sort @ARGV; # Ordenación alfabética
for ( my ($index) = $#ARGV; $index > 0; $index-- ) { # Para todos los directorios a procesar
if ( $ARGV[$index] =~ m|^$ARGV[$index-1]|i ) { # Si ese directorio es un subdirectorio del anterior
splice( @ARGV, $index, 1 ); # Lo sacamos del array (no lo procesaremos)
}
}
map {s|:/$|:\\|} @ARGV; # Caso de directorios MSDOS, restituímos el ':\' del principio
my ( $rhha, $f_DoNotInsert );
find( { # Búsqueda de todos los archivos y directorios
wanted => \&TreatThisFile, # Ejecutamos esto cada vez que encontremos uno
preprocess => \&PreTreatThisDirectory, # Ejecutamos esto antes de procesar un directorio
},
@ARGV # Para todos los directorios
);
foreach my $s_Directory (
sort { uc $a cmp uc $b } keys %$rhha
) { # Sacamos la estructura leída, a partir de las claves
# del hash, ordenada alfabéticamente, sin importar
# el tamaño de caja
print "$s_Directory\n"; # Bandera que indica si es un directorio
foreach my $s_Extension (
sort { $a cmp $b } keys %{ $rhha->{$s_Directory} }
) { # Ordenado según la extensión del archivo
foreach my $s_Filename (
sort { uc $a cmp uc $b } @{ $rhha->{$s_Directory}{$s_Extension} }
) { # Para todos los archivos
print "$s_Filename\n"; # Imprimimos su nombre
}
}
}
sub PreTreatThisDirectory { # Ejecuta esto por cada directorio
$f_DoNotInsert = exists $rhha->{$File::Find::dir}; # No añadir el directorio si ya lo hicimos antes
return @_;
}
sub TreatThisFile { # Ejecutar esto por cada archivo/directorio
my ($s_Path);
if ( -d ( $s_Path = $File::Find::name ) ) { # Si es un directorio...
} # ... no hacemos nada
else { # Si es un archivo...
my ( $s_Name, $s_Directory, $s_Extension )
= fileparse( $s_Path, '\.[^.]*' ); # Partimos toda la ruta en nombre del archivo,
# el directorio y su extensión
push( # Guardamos
@{ $rhha->{$s_Directory}{ uc $s_Extension } }, # el nombre del archivo en una estructura bidimensional,
# según el directorio y la extensión que tuviera
"$s_Name$s_Extension"
) unless ($f_DoNotInsert); # excepto si ese directorio no hay que guardarlo
}
}