#!/usr/bin/perl -w
#by Torben Menke
#http://tokes.to.funpic.de
# functions for working on filenames and folders

use File::Spec;
use warnings;
use strict;
use Data::Dumper;
use Encode;



# /tmp/dir1/dir2/filename.txt -> /tmp/dir1/dir2
sub getPathFromFile {
my @dir = File::Spec->splitdir( shift );
pop @dir; # remove last item (= filename)
return File::Spec->catdir(@dir);
}


# /tmp/dir1/dir2/filename.txt -> filename.txt
sub getNameFromFile {
my @dir = File::Spec->splitdir( shift );
return pop @dir;
}


# getsubfiles (DIR) -> list of all files under that startdir
# work also if DIR is a list
sub getsubfiles {
my @lst = @_;
my @return;
while (my $startdir = shift @lst) {
if (-f $startdir) {
@return = (@return, $startdir);
next;
}
next if ($startdir=~m#/\.# or $startdir=~m#^\.# or not -d $startdir);

my (@files,@dirs) = ((),());
my @dircont = ();

opendir DIR, $startdir or die "'$startdir' :$!\n";
@dircont = readdir DIR;
closedir DIR;
#TODO UTF-8 specific!!!
@dircont = map {decode('utf8',$_)} @dircont;
@dircont = grep {!m/^\.\.?$/} @dircont;
@dircont = map {join_dir($startdir,$_)} @dircont;

# split into files and dirs
next if ($#dircont == -1);
while (my $i = shift @dircont) {
$i .= '';
next if ($i eq '' );
if (-f $i) {
@files = (@files, $i);
} elsif (-d $i and not $i=~m#/\.# and not $i=~m#^\.#) { # no hidden dirs
@dirs = (@dirs, $i);
}
}
# sort the dirs case insensitive
@dirs = sort {uc($a) cmp uc($b)} @dirs ;

foreach my $d (@dirs) {
@return = (@return, getsubfiles($d))
}
@return = (@return, sort {uc($a) cmp uc($b)} @files);
}
return @return;
}


# getsubdirs (DIR) -> list of all sub-dirs under that startdir
# work also if DIR is a list
sub getsubdirs {
my @lst = grep {not m#/\.# and not m#^\.# and -d} @_;
my @return;
while (my $startdir = shift @lst) {
@return = (@return, $startdir);
my @dirs;
opendir DIR, $startdir or die "'$startdir' :$!\n";
my @dircont = readdir DIR;
closedir DIR;
#TODO UTF-8 specific!!!
@dircont = map {decode('utf8',$_)} @dircont;
@dircont = grep {!m/^\./} @dircont; # no hidden dirs and not '..', '.'
@dircont = map {join_dir($startdir,$_)} @dircont;
@dirs = grep {-d $_} @dircont;

# sort the dirs case insensitive
@dirs = sort {uc($a) cmp uc($b)} @dirs ;

foreach my $d (@dirs) {
@return = (@return, getsubdirs($d))
}
}
return @return;
}


# joins "$dir/$path", but make it also work in windows
sub join_dir {
my @dir = File::Spec->splitdir( shift );
my @path = File::Spec->splitdir( shift );
push @dir,@path;
return File::Spec->catdir(@dir);
}



1; # Last line: must return a 1 for allowing it to be included into other files

Hope you found what you where looking for. Feel free to drop me a line
Torben