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

I want to get the list of files that are in one directory. The only method to do this that I have found till now is
@list = (<*>)
But when the directory contains a file which name contains a blank character, I have two entries for it in my list, e.g. :

if there is file called "aaa bbb", the list is (... ,"aaa", "bbb", ...) but I want (... ,"aaa bbb", ...) Anyone knows where the solution dwells ?

Replies are listed 'Best First'.
Re: file with a blank in its name
by marcos (Scribe) on May 05, 2000 at 15:02 UTC
    I would use opendir and readdir:
    opendir (DIR, $dir) or die "cannot opendir $dir"; my @files = readdir(DIR); closedir (DIR);

    if you want only files (no subdirectory) you may use:
    opendir (DIR, $dir) or die "cannot opendir $dir"; my @only_files = grep {-f "$dir/$_"} readdir(DIR); closedir (DIR);

    marcos
      If you're retrieving all filenames using opendir and readdir (which is the way I usually do it), then you'll want to filter out at least directories (and possibly smylinks as well)
      Here's one way to do it (modified from example in The Perl Cookbook):
      $dir = 'path/to/directory'; opendir(DIR, $dir) or dir "Can't open $dir: $!"; while (defined($file = readdir DIR)) { #Test if $file is a directory unless (-d "$dir/$file") { #Test if $file is a symlink unless (-l "$dir/$file") { #push $file onto @list push(@list,$file); } } }
Re: file with a blank in its name
by BBQ (Curate) on May 05, 2000 at 16:43 UTC
    my $path = '/home/bbq/tmp'; my @contents = glob($path);
    You'll have to sort out what got thrown into @contents if all you really want are just the files (you'll get files, dirs, sym links, devs, the whole gazoo). You could do a few checks before using each @contents. If you want a recursive example, I posted something a while back on this node which might be of interest.

    HTH

    #!/home/bbq/bin/perl
    # Trust no1!
Re: file with a blank in its name
by athomason (Curate) on May 05, 2000 at 14:18 UTC
    You want to use readdir instead. You should just be able to replace the (<*>) construct with that (you'll need to open a directory handle first, though).
Re: file with a blank in its name
by takshaka (Friar) on May 06, 2000 at 00:09 UTC
    While I agree with everyone that suggests readdir over glob for anything but a quick hack, is this a platform-dependent problem (ie, a shell thing)? Both 5.6 and 5.005_03's glob work fine for me on Linux:
    chh@scallop ~> touch "Foo bar" chh@scallop ~> perl -le 'print grep /\s/, <*>' Foo bar chh@scallop ~> perl -le '@f = <*>; print grep /\s/, @f' Foo bar
    I'm on the road and don't have access to a Windows box to check, but I seem to remember something funky about Win32's glob and long filenames.
      It works for me with both ActiveState 522 and 613 (that's 5.005_3 and 5.6, for those of you keeping score) on NT. My test program was:
      my @files = grep /\s/, <*>; foreach my $file (@files) { print ">>$file<<\n"; }
      On both versions, that caught long filenames successfully. On a Linux box with GNU bash, version 1.14.7(1) and Perl 5.005_3, it works as well.

      (since the Win98 box has become a Linux Distribution Installer Testbed, I can't report on that. :)

      I had heard in the past that ActiveState's distribution had a quirky glob, it that it would only return the correct values for "*.*" instead of "*", but I have just run a test on a NT box and this is what I got...
      Orders, Sir? cd \usr\local Orders, Sir? ls -la total 0 -d---- 0 3-Mar-100 03:28 . -d---- 0 3-Mar-100 03:28 .. -d---- 0 3-Mar-100 03:29 apache -d---- 0 15-Apr-100 21:37 bin -d---- 0 7-Dec-99 03:34 cgi-bin -d---- 0 6-Dec-99 21:58 ftpd ad---- 0 24-Feb-100 18:24 httpd -d---- 0 7-Dec-99 02:19 iissamples -d---- 0 22-Apr-100 22:45 mysql -d---- 0 6-Dec-99 21:58 scripts -d---- 0 7-Dec-99 21:11 uia Orders, Sir? perl foreach (glob("*")) { print ++$x.". $_\n"; } ^Z 1. apache 2. bin 3. cgi-bin 4. ftpd 5. httpd 6. iissamples 7. mysql 8. scripts 9. uia Orders, Sir?
      Apart from the current directory and the parent directory, everything got listed, exactly as it would on a real system. (and I know the contents of \usr\local don't look too much like an NT box, but beleive me! It is! I just don't like the stuff that ships with NT)
      Well, to close the book on the tests, I checked ActiveState 522 on Win98SE and got the same results as on NT. <*> returns long filenames--with or without extensions, with or without spaces--and does not do an implicit split on the list when assigning to an array. I can't reproduce the behavior cited by the OP.

      However, in spite of all evidence to the contrary, I still believe there are some issues with 522's glob.

RE: file with a blank in its name
by Anonymous Monk on May 05, 2000 at 19:01 UTC
    You should have tried to use: @list = (<"*">) instead of: @list = (<*>) -Fariz-
Re: file with a blank in its name
by Anonymous Monk on May 05, 2000 at 23:43 UTC
    I know this doesn't really answer your question, but I would really recommend using

    @files = glob("*"); rather than @files = <*>;

    Using the glob function makes your code far clearer. Imagine someone new to Perl looking at your script -- even finding entries for < > in the manual are going to be harder!

Re: file with a blank in its name
by t0mas (Priest) on May 05, 2000 at 21:01 UTC
    I usually use
    opendir(DIR, $rDir) || die "Can't opendir $rDir: $!"; my @files = grep { -f "$rDir/$_" } readdir(DIR); closedir DIR;
    /t0mas