in reply to Directory listing

@farmLs = `ls -ltr /usr/local/farm/*/*/input/`;

It's always somewhat disconcerting when I see someone writing shell scripts inside their perl code ... I'm not sure where I first heard it, but the old saying that "you can write ForTran in any language" is just as true about any other seriously limited language (e.g., batch files or shell scripts)...

Especially when perl has the ability to do this already.

require File::Spec; @farms = glob( File::Spec->catfile( qw(usr local farms * * input), "*$corp*" ) );
This gives us a full program like this:
#!/usr/bin/perl # # This is a program that is intended to allow FEP operators # a tool that will facilitate in monitoring incoming transmissions # and preprocessor logs. # #------------------- Define Subroutines ------------------# # lsForCorp Subroutine designed to take an argument and do a directory # listing looking for that argument on the farm and then returning the + # results. use strict; sub lsForCorp { my $corp = $_[0]; require File::Spec; my $path = File::Spec->catfile( File::Spec->rootdir(), qw(usr local farms * * input), "*$cor +p*" ); my @farms = glob($path); foreach my $farm (@farms) { print $farm, "\n"; } # end of foreach statement } #end of lsForCorp subroutine #------------------- End Subroutines ---------------------# print "What corp are you looking for? " ; chomp(my $whatWeWant = <STDIN>); lsForCorp($whatWeWant);
Note a number of changes - no more local, using strict, a few minor changes to variables, and especially using my all over the place, getting rid of the & in front of calling a function, chomping your input (that was likely your original problem there), using the glob as above - which eliminates the if statement in your loop. My not-so-humble opinion that this is not only correct (I tested it here), but better perl code ;-) Hope it helps.

Replies are listed 'Best First'.
Re^2: Directory listing
by FireyIce01 (Novice) on Jan 17, 2005 at 05:03 UTC
    Awesome, that is a good start... now if I get rid of the input and just have
    qw(usr local farms * *), "*$corp*"
    Will it do a recursive search through log, input, save, failed, etc? or will I have to make a seperate subroutine for each of those paths?

    Also, would you be willing to do a small breakdown of what each line is actually doing (only the one's you changed, I should hope I know what the ones I wrote were doing) so I'm not just taking prefabbed code... I'd like to relearn this (I never really got far with perl in the first place, so I guess learn would be a better word than relearn)

    Also, with glob, is there some way that I can get the date, time, and bytecount of the files being returned?

      Here's some comments in-line:

      # supersearch this one - short version: it detects most common coding +errors. # always use it. use strict; sub lsForCorp { my $corp = $_[0]; # File::Spec allows you to create a directory structure in # a platform-independant manner. Not a big deal to you since # this probably only runs on unix anyway, but all my code # has to run on both unix and Windows, so it's just a # habit. require File::Spec; my $path = File::Spec->catfile( # this reconstructs the path - if you print $path, you'll # see exactly the path you were using - again, no big deal # if portability is unimportant (and "/usr/local" is not # really portable either ;->) File::Spec->rootdir(), qw(usr local farms * * input), "*$cor +p*" ); # let glob do all the work rather than ls. Besides, ls # calls the same thing as glob under the covers, more or # less. (Technically, it's the shell.) my @farms = glob($path); foreach my $farm (@farms) { # no if statement since the glob already only gets files that match # *$corp*, which is the glob way of saying /\Q$corp/. print $farm, "\n"; } # end of foreach statement } #end of lsForCorp subroutine #------------------- End Subroutines ---------------------# print "What corp are you looking for? " ; # chomp it to remove the trailing newline. chomp(my $whatWeWant = <STDIN>); # & doesn't do what you think it does - avoid it unless you # actually mean to do what it does. lsForCorp($whatWeWant);

      If you want to search more than just "input", you want to search all directories at that level, you just change "input" to "*", and it'll handle that: /usr/local/farms/*/*/*/*$corp*. As long as everything is at the same depth in the directory tree, this works fine. If you're looking for files at different depths, you'll need to use File::Find or something similar.

      As for getting the date/time/bytecount, you'll need to use the -X functions and/or stat or File::stat. e.g.:

      use File::stat; # ... my $s = stat($farm); printf "%s: Age [%s], size [%d]\n", $farm, $s->mtime(), $s->size();

        Alright, I'm trying to get the date to be human readable... I figured the best thing for this is Date::Manip, however, I can't seem to get the filestat information into the datemanip...
        foreach my $farm (@farms) { my $s = stat($farm); printf "%s: Age [%s], size [%d]\n", $farm, &ParseDateString("epoc +h $s->mtime()"), $s->size(); } # end of foreach statement
        I've tried a couple things, but nothing I try seems to work...

        here's the entire script so far:

        #!/usr/bin/perl use strict; use File::stat; use Date::Manip; # This is a program that is intended to allow FEP operators # a tool that will facilitate in monitoring incoming transmissions # and preprocessor logs. #------------------- Define Subroutines ------------------# # # # Main is a subroutine simply written for flow control sub Main { my $corp = $_[0]; print "Input:\n"; farmInput($corp,'input'); } # end Main # farmInput does a wildcard search of all /usr/local/farm/*/*/input fo +lders # looking for the <STDIN> corp number and printing those files to scre +en. sub farmInput { my $corp = $_[0]; my $finalPath = $_[1]; my $path = "/usr/local/farm/*/*/$finalPath/*$corp*"; my @farms = glob($path); foreach my $farm (@farms) { my $s = stat($farm); printf "%s: Age [%s], size [%d]\n", $farm, &ParseDateString("epoc +h $s->mtime()"), $s->size(); } # end of foreach statement } # end farmInput #------------------- End Subroutines ---------------------# print "What corp are you looking for? " ; chomp(my $whatWeWant = <STDIN>); Main($whatWeWant);
        I'm trying to streamline it as I go, I know that in the farmInput subrouting I could put the $corp and $finalPath variables on the same line, just haven't gotten to that yet... I'd like my code to be as small and clean as possible... but it needs to work first! ;o)