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

hey monks , since I am new to perl. my question might seems real easy +. I have the following -rw-rw-r-- 1 kp3194 oper 0 Sep 29 09:20 file1 -rw-rw-r-- 1 kp3194 oper 165 Sep 29 09:20 file2.sql I need to use split to only get the files name somthing like file1 file2.sql I am doing $file = split(/\s*/,12);

Replies are listed 'Best First'.
Re: split to get the dir name
by davis (Vicar) on Sep 29, 2003 at 15:35 UTC

    Warning: Assumptions ahead. I may be entirely wrong.
    From your example input, I'd hazard a wild guess that you're parsing the output of ls -l. I'm going to make the assumption that you're running ls -l with something like the backticks operator, and you're trying to parse the output.

    If my above analysis is correct, then you're creating work for yourself, not to mention the person that would have to mantain it. A much more reasonable way to do what I'm assuming you want to do is:

    use strict; use warnings; my $some_dir = "/tmp"; opendir(DIR, $some_dir) or die "can't opendir $some_dir: $!\n"; my @files = readdir(DIR); closedir DIR; print join "\n", @files;

    If that looks useful, you may wish to look at perldoc -f readdir

    cheers
    davis
    It's not easy to juggle a pregnant wife and a troubled child, but somehow I managed to fit in eight hours of TV a day.
Re: split to get the dir name
by jeffa (Bishop) on Sep 29, 2003 at 15:34 UTC
    Why not do it The Right Way™ with File::Basename instead?
    use File::Basename; my @file = qw(/path/to/file1 /path/to/file2.sql); print basename($_),"\n" for @file;
    UPDATE:
    I didn't realize that our questioner was using the output of 'ls -la' (even though it is more than obvious to me now). Please don't do that. davis's suggestion is a much better one.

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
Re: split to get the dir name
by dragonchild (Archbishop) on Sep 29, 2003 at 15:34 UTC
    open(LS, 'ls -l|') or die "Cannot open 'ls -l' for reading\n"; while (<LS>) { chomp; #Added after some thought. my $filename = (split ' ', $_)[-1]; print "$filename\n"; } close LS;

    There's a whole bunch of Perl idioms in that line. split on ' ' is magical. It does the same thing as /\s+/. Negative indices for arrays count from the end. So, index -1 is the last element. I'm also using an implicit list populated with the result of the split.

    ------
    We are the carpenters and bricklayers of the Information Age.

    The idea is a little like C++ templates, except not quite so brain-meltingly complicated. -- TheDamian, Exegesis 6

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

      Quothe dragonchild:
          my $filename = (split ' ', $_)[-1];

      But what if the filename contains a space?

      ------------------------------------------------------------
      "Perl is a mess and that's good because the
      problem space is also a mess.
      " - Larry Wall

        Then split will break. You'd have to go with substr (which would be platform-dependent) or change the ls pipe from 'ls -l' to 'ls -1'. *shrugs*

        ------
        We are the carpenters and bricklayers of the Information Age.

        The idea is a little like C++ templates, except not quite so brain-meltingly complicated. -- TheDamian, Exegesis 6

        Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

      why -l? He only wants the file names, right? And why are you assuming that AM is executing the "ls -l" in his script? Maybe he is reading in a old log file or something else.
      update
      -l as in "ls -l" not 1 as in 1 2 3. My point being if AM is executing "ls -l" and dealing with the output of "ls -l" it would be simplier to execute "ls" with no options. The output of that is simplier to deal with and AM could avoid using split all together.
      update again
      open(LS, 'ls|') or die "Cannot open 'ls' for reading\n"; while (<LS>) { chomp; #Added after some thought. print "$_\n"; } close LS;

      You can't do this to me! I went to college!
Re: split to get the dir name
by welchavw (Pilgrim) on Sep 29, 2003 at 16:46 UTC

    Hi,

    Please forgive if you know this already, especially as it doesn't address your immediate question. The rest of the comments to this point should very readily help you through your current problem...but getting the contents of a directory is more easily, quickly and safely done without handing off to a shell.

    my @filelist = glob './*'; #get filelist of curdir

    ,welchavw

      I was about to whine that welchavw's code would not produce the right results in the Win32 environment, but it does!. I wonder how it would fare on the Mac - seems like it should work there too.

      Anyway - here is a minor variation on his code to enable processing/printing:

      foreach( glob './*'){ print qq($_\n); # if necessary # Do some work with the file name (available as $_) };
Re: split to get the dir name
by vek (Prior) on Sep 29, 2003 at 17:25 UTC

    Other monks have given you some good answers here. If you really have no alternative to parsing the output from ls -l then have a peek at File::Listing. I've had to parse the output from ls -l over an FTP connection and File::Listing was perfect for that.

    -- vek --
      If you were looking for just the files and not any directories, then try this,
      #!/perl -w use strict; ##Code is tested on winxp with perl 5.8## my $path = "c:\\"; my @files; #Open the directory opendir(AMHANDLE,$path); #iterate over the file handle while(my $file = readdir(AMHANDLE)) { #print $file ."\n"; #If the file is a folder then just echo it if(-d $path.$file) { print "$file is a folder\n"; } else { #Else push it onto the files array push @files,$file; } } #Close the handle closedir(AMHANDLE); #Echo the contents of the @files array foreach my $item(@files) { print $item . "\n"; }

      Yes I know that in *NIX that directories are just special case files, but I didn't know if the poster meant files or simply the contents. Please understand that I'm not trying to sound like a know-it-all because everyone probably knows by now that I'm not. I just wanted to offer a few other tidbits of knowledge to AM.

        thanks all
Re: split to get the dir name
by Plankton (Vicar) on Sep 29, 2003 at 15:33 UTC
    You probably want to use substr.

    Plankton: 1% Evil, 99% Hot Gas.
      To elaborate on the substr approach, if you know the absolute position that something occurrs within a string, substr is a lot faster and less confusing to regexp novices than a regular expression or split.

      For example, if your string looks like this:

      my $str; $str = "drwxr-xr-x 2 jonnyq jonnyq 4096 Sep 21 18:52 bin";

      And each directory item starts the 'filename' portion of the listing at the same absolute column, (in this case, 56, starting counting from 0), then you can extract everything from that column to the end of the string with:

      my $file = substr $str, 56;

      If you really want to use a regular expression, and you know that the filename always occurs at the end of the line, and that it cannot contain whitespace you can do it like I've done in the following example (which won't work if you're in a situation where filenames my contain whitespace).

      if ( $string =~ /\s(\S+)\s*$/) { print $1, "\n" };

      This method anchors your search to the end of the line (and at the same time allows trailing whitespace to be ignored). You're telling the regexp engine to match only non-space characters, preceeded by a space character, at the end of the line.

      Of course if whitespace is permitted in your file name, the regexp method becomes a lot more difficult (and split also won't work).

      Unless you're interested in each field preceeding the filename, I don't see a need for split. However, if your homework assignment requires it, you may do this:

      my $filename = (split /\s+/, $string)[-1]; print $filename, "\n";

      Dave

      "If I had my life to do over again, I'd be a plumber." -- Albert Einstein

        (which won't work on Win32 because Win32 filenames my contain whitespace, but works fine on Linux)

        What makes you think Linux filenames can't contain spaces?


        We're not surrounded, we're in a target-rich environment!