madM has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks! im trying to read all files (except of hidden files ) in a directory and work with them ..any suggestions ?
my @folder=(); opendir (DIR,"/Users/Maxi/Desktop/Verzeichnis\ beispiel") or die " the + directory couldn´t be opened\n"; while (@folder = readdir(DIR)){ last; } foreach my $file (@folder){ open( FIL ,'<', $file) or die "the file $file couldn´t be opened: +$!\n"; #### here something else to do with each file#### }

Replies are listed 'Best First'.
Re: working with directories
by choroba (Cardinal) on Sep 12, 2013 at 11:58 UTC
    There is no need to backslash spaces in path in Perl. Also, using while when you call readdir in list context and the only thing you do in the loop is last is unorthodox.

    Also note that readdir returns the file names, but you have to prefix the path to them. Also, you only want to open files, not subdirectories, so I used grep to filter those out.

    #!/usr/bin/perl use warnings; use strict; my $path = '/Users/Maxi/Desktop/Verzeichnis beispiel'; opendir my $DIR, $path or die " the directory couldn't be opened\n"; my @folder = grep -f "$path/$_", readdir $DIR; for my $file (@folder) { open my $FIL ,'<', "$path/$file" or die "the file $file couldn't b +e opened: $!\n"; while (<$FIL>) { print if /perl/i; } }
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
      thanks a lot! i wrote this code in an attempt of reading and working with all the files in a directory but it doesnt work... yet if i specify the path of one file i get results im still a perl beginner so don´t laugh at my code ^^ thanks!
      print "Enter a directory´s path to work with all files in a folder or +a single file path\n\n"; chomp(my $input =<STDIN>); if ($input =~ /./){ ### attempt of recognizing a file extention $datei = $input; open(my $fastd,'<', $datei) or die "die datei $datei wurde nicht g +eöffnet: $!\n"; while (my $line = <$fastd>) { #reading fasta file chomp $line; if ($line =~ /^>/) { $header = $line; $header =~ s/>//g; } else { $sequences->{$header} .= $line } } }elsif($input =~ /[^.]/){ #### attempt of recognizing just a folder b +ut i know it wont work always $path = $input; opendir my $DIR, $path or die " the directory couldn't be opened\n +"; my @folder = grep -f "$path/$_", readdir $DIR; for my $file (@folder){ open (my $fastd ,'<', "$path/$file") or die "the file $file co +uldn't be opened: $!\n"; while (my $line = <$fastd>) { #reading fasta file chomp $line; if ($line =~ /^>/) { $header = $line; $header =~ s/>//g; } else { $sequences->{$header} .= $line } } } }
        What do you mean by "doesnt work"? Is there an error or warning, or does nothing happen, does the computer hang or burn in flames?

        Dot has a special meaning in regular expressions. To match a literl dot, use /\./.

        Also, you should use -d to test whether something is a directory - directory names with extensions are also valid.

        لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: working with directories
by tobyink (Canon) on Sep 12, 2013 at 12:03 UTC

    Your while loop is pretty useless.

    while (@folder = readdir(DIR)){ last; }

    ... is basically a convoluted way of writing:

    @folder = readdir(DIR);

    Generally speaking, I'd recommend Path::Tiny as a much easier way of dealing with files and directories than Perl's built-ins.

    use Path::Tiny 'path'; my $dir = path('/Users/Maxi/Desktop/Verzeichnis beispiel'); for my $file ($dir->children) { next if $file->is_dir; my $fh = $file->openr; while (my $line = <$fh>) { ...; } }
    use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name
Re: working with directories
by Laurent_R (Canon) on Sep 12, 2013 at 11:59 UTC

    You failed to tell us what your problem is. Are we supposed to guess?

    You don't need a while loop if you are reading the directory in list context:

    my @folder = readdir DIR;

    You may also take a look at the glob function, which is often more practical than opendir/readdir.

Re: working with directories
by Anonymous Monk on Sep 12, 2013 at 12:19 UTC
Re: working with directories
by uday_sagar (Scribe) on Sep 13, 2013 at 05:26 UTC

    Hello,

    You can get the same functionality using glob operator(as LaurentR has said) and with fewer lines of code.

    Here you go!

    #!/usr/bin/perl my @files = glob( "$ARGV[0]/*.*" ); for my $file (@files) { open NB_FILE, '<', $file or die "Couldn't open Netbackup file!"; while(<NB_FILE>) { print "Printing line $. from file $file\n"; print $_; } close NB_FILE or die "Couldn't close the file properly!" }
Re: working with directories
by zork42 (Monk) on Sep 13, 2013 at 04:49 UTC
    Are you aware of the file test operators?

    A better way of writing this (copied from your Re^2: working with directories post)
    print "Enter a directory´s path to work with all files in a folder or +a single file path\n\n"; chomp(my $input = <STDIN>); if ($input =~ /./){ ### attempt of recognizing a file extention ... process file }elsif ($input =~ /[^.]/){ #### attempt of recognizing just a folder +but i know it wont work always ... process folder }
    Would be something like this:
    print "Enter a directory´s path to work with all files in a folder or +a single file path\n\n"; chomp(my $input = <STDIN>); if (-f $input){ # $input is the name of an existing file ... process file }elsif (-d $input){ # $input is the name of an existing folder ... process folder }