Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

Loop Break

by stallion (Acolyte)
on Jan 19, 2012 at 15:37 UTC ( #948792=perlquestion: print w/replies, xml ) Need Help??
stallion has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks im trying to get the file names in a directory ..but its getting repeated again and again..Pls rectify

foreach $file (<*.*>) { if($file =~ /\.c/) { $filename = $file; print m"$filename\n"; } }

Replies are listed 'Best First'.
Re: Loop Break
by TomDLux (Vicar) on Jan 19, 2012 at 18:33 UTC

    There's enough up there about the correct use of glob() and of m{}.

    I'd like to point out it's silly to glob on *.* and then ignore anything not matching *.c. Be more specific in the glob and you won't need the internal condition:

    use 5.010; say for glob '*.c'; # or if you're doing more than using the filename once .. for my $file ( glob '*.c' ) { print $file, "\n"; lots_of_complicated_code( $file ); }

    As Occam said: Entia non sunt multiplicanda praeter necessitatem.

Re: Loop Break
by ww (Archbishop) on Jan 19, 2012 at 16:18 UTC
    Angle_brackets don't work that way.

    To get an array of filenames, see open, opendir Duh! Sorry, readdir, or any number of threads here (hint: Super Search with terms like "dir files" or similar).

    Of course, you could make your list with

    ls -la /dirpath/dir/ > file_of_names
    dir /a /dirpath/dir/ > file_of_names
    But this is, after all, a perl forum.

    Moving on, your regex would (if the script worked) catch files with names like pqr.cobol so you might consider this:

    #!/usr/bin/perl use Modern::Perl; use Diagnostics; my (@file, $file, $filename); @file = <DATA>; for $file (@file) { if($file =~ /\.c$/i) { # match only filenames ending in ".c" or ". +C" $filename = $file; print "$filename\n"; } } __DATA__ bzz.c bzz.doc pqr.cobol 123.1c def.C foo.endswithC

    For the record, though, your regex does achieve a good many proper exclusions

    bzz.doc             \
    123.1c               # not matched by your regex, ++
    foo.endswithC /
    Update: fixed brain-fart in para 1
      Angle_brackets don't work that way.
      They do.
      perldoc -f glob
        ++ for your reply, JavaFan because I was misreading this (from the glob doc you cited):
        Note that "glob" splits its arguments on whitespace and treats each segment as separate pattern. As such, "glob("*.c *.h")" matches all files with a .c or .h extension. The expression "glob(".* *")" matchs all files in the current working directory.

        Nothing there bars this:

        #!/usr/bin/perl use Modern::Perl; my @arr = glob("*.*"); for my $line(@arr) { say $line; }

        Also, as noted by Corion, perlop is relevant.

        If what the angle brackets contain is a simple scalar variable (e.g., +<$foo>), then that variable contains the name of the filehandle to in +put from, or its typeglob, or a reference to the same. For example: $fh = \*STDIN; $line = <$fh>; If what's within the angle brackets is neither a filehandle nor a simp +le scalar variable containing a filehandle name, typeglob, or typeglo +b reference, it is interpreted as a filename pattern to be globbed, a +nd either a list of filenames or the next filename in the list is ret +urned, depending on context.

        Above blockquote added as an update, for future readers

        TY, both!

Re: Loop Break
by RichardK (Parson) on Jan 19, 2012 at 16:28 UTC

    You could use glob to get the file names. Something like

    for my $file (glob('*')) { stuff }

    But do check the help first, glob takes a file match pattern NOT a regex :)

Re: Loop Break
by toolic (Bishop) on Jan 19, 2012 at 17:51 UTC
    Check to see if your code is what you thought it was, using B::Deparse (Tip #6 from the Basic debugging checklist) :
    use File::Glob (); foreach $file (glob('*.*')) { if ($file =~ /\.c/) { $filename = $file; print /$filename\n/; } }
    As Anon points out, you're really using m///
Re: Loop Break
by sundialsvc4 (Abbot) on Jan 19, 2012 at 16:27 UTC

    The way that I routinely deal with things like this is to use File::Find, or File::Find::Object, or any one of their many brethren.

    Basically, my thought is, a very complete and well thought out solution to this very well-known task is at my fingertips, so I’m gonna grab it and use it and move on.   I encourage you to do likewise.

    Also, and on a more general level, sometimes file-searches will be disrupted by things that you do to those files or to the filesystem within that loop.   This seems to be particularly true in Microsoft Windows.   Therefore, my customary approach is to build the list-of-files first, explicitly close the search, and then to go back and process that list.   The exact details depending upon the number of files that I expect to see.

Re: Loop Break
by Anonymous Monk on Jan 19, 2012 at 15:59 UTC
    error m"$filename\n"; this means  m/$filename\n/;

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://948792]
Approved by ww
and a kettle whistles...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (7)
As of 2017-06-24 01:15 GMT
Find Nodes?
    Voting Booth?
    How many monitors do you use while coding?

    Results (555 votes). Check out past polls.