Solved

`dir $dosdir`; stopped working

Posted on 2003-11-12
11
367 Views
Last Modified: 2010-03-04
Greetings:

I have a perl script that's been running for years.  I'm using 5.6.1 by activestate for Win32 on a NT4.0 server.

A week or so ago, my script stopped working.  I suspect it's due to someone patching the NT server (I don't administer it).  But I have no way to know...

The problem appears to be at least with my command which gets a sorted by date directory list.  I ran this debug snippet to test:

@filelist=`dir \httpd\testing /OD /B`;

print "BEGIN\n";
for (@filelist) {
      chomp;
      $file = $_;
  print "Processing: $file\n";
}
print "END\n";


All I get for output is:

BEGIN
END

The directory has 3 files in it and all are not read-only, just archive flag set.

Any suggestions?

Thanks very much for the help.  I am not a perl guru so if possible answers in laymen form appreciated.

Thanks,
Scott








0
Comment
Question by:scotthorton
  • 3
  • 3
  • 2
  • +3
11 Comments
 
LVL 6

Expert Comment

by:sstouk
ID: 9733691
I suppose you already restarted the NT Server and tested your script again?
0
 
LVL 6

Expert Comment

by:sstouk
ID: 9733725
As a worst-case scenario here's the modification for your script:
#######################################
# @filelist=`dir \ /OD /B`;
@filelist2 = main::ListFiles("/httpd/testing",0,"*.*");
print "BEGIN\n";
for (@filelist2) {
# chomp;
     $file = $_;
  print "Processing: $file\n";
}
print "END\n";


##############################################################################
sub main::ListFiles
{
my(@FILENAME) = undef;
my($dirname) = $_[0];
my($fullnameswitch) = $_[1];
my($pattern) = $_[2];
my($count) = 0;
my($file) = undef;
if($pattern) {$pattern =~ s/\*/\.\*/g; $pattern = "^"."$pattern"."\$"};
if ($dirname =~ m!/!)
{
      unless ($dirname =~ m!/$!)
      {
      $dirname = "$dirname"."/";
      };

} else {
            unless ($dirname =~ m!\$!)
            {
            $dirname = "$dirname"."\\";
            };
      };
opendir(DIR, $dirname) or warn "can't opendir $dirname: $!";
      while (defined($file = readdir(DIR)))
      {
      next if $file =~ /^\.\.?$/;
      next if (-d "$dirname$file");
            if (($file =~ /$pattern/g) && (-f "$dirname$file"))
            {
            # print "FILE: $file\n<br>";
                  if ($fullnameswitch)
                  {
                  $FILENAME[$count] = "$dirname"."$file";
                  $FILENAME[$count] =~ s/\\\\/\\/;
                  $FILENAME[$count] =~ s/\\/\//;
                  $count++;
                  } else {
                        $FILENAME[$count] = $file;
                        $count++;
                        };
            } else {
                  
                  };
      }
closedir(DIR);
return @FILENAME;
};
##############################################################################
0
 

Author Comment

by:scotthorton
ID: 9733759
Yes, I restarted server first, no avail.

As for the code above, it does not sort file list in date order.  Does it?  Processing the files in date order is a requirement for the rest of the app.

Thanks,
Scott


0
 
LVL 84

Expert Comment

by:ozo
ID: 9734757
@filelist=`dir \httpd\testing /OD /B`;
should be
@filelist=`dir \\httpd\\testing /OD /B`;
0
 

Author Comment

by:scotthorton
ID: 9734967
My apologies.  I do have the "\\" in the existing code.  I couldnt' cut and paste because the source PC is on a secure network.  Sorry, but thanks very much for the detailed look.  Still not working.  Same script works on a different computer, pretty much points at something they've done to the NT server.  I and the account the script runs under have full administrative rights and the server is not a member of any other domain.

:-(

0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
LVL 18

Expert Comment

by:kandura
ID: 9736034
here's a short subroutine that will get your list, sorted by modification date (oldest first). Pass the directory as first and only argument.

sub my_dir
{
      my $dir = shift;
      
      opendir(DIR, $dir) or die "Couldn't read dir $dir: $!";
      my @files = map { $_->[1] }                         # return filenames
                  sort { $b->[0] <=> $a->[0] }              # sort on modification time
                  map { [ -M "$dir/$_", $_] }                  # do a Schwartzian transform
                  grep { !/^\.+$/ }                         # skip . and ..
                  readdir(DIR);
      closedir DIR;

      @files;      # return as array
}
0
 
LVL 2

Expert Comment

by:ext2
ID: 9752379
does

   dir \httpd\testing /OD /B

work from the DOS command prompt?
0
 

Expert Comment

by:Teh_Craze
ID: 9757496
Here; Make sure, when specifying directories, or when any backslash is needed, to escape it, and, for safty, allways put a trailing backslash to indicate it's a directory.

@filelist=`dir \\httpd\\testing\\ /od /b`;

print "BEGIN\n";
for (@filelist) {
     chomp;
     print "Processing: $_\n";
}
print "END\n";



0
 
LVL 18

Accepted Solution

by:
kandura earned 201 total points
ID: 9760517
Hi Scott,

I don't think you told us this, but what's the output from that dir command when you run it directly from the command prompt?
Is your script on the same drive as that httpd directory?
What happens when you change the `dir ...` to a simple `dir` command? Does your script list the same output as a direct dir command?

Just checking,
Kandura

PS, did you get a chance to test my subroutine? It should work, or tell you why it doesn't work. And it's platform-independent ;^)
0
 

Author Comment

by:scotthorton
ID: 9765089
Kandura, et.al.:

THanks very much for the help.  I found the problem on my own.  It was where someone installed something on the NT server that inserted a non-existant directory into the path.  As someone usggested above, I of course tried the "dir" command from the directory and it worked.  Funny thing was though that a ls would not, even though a ls.exe was inthe path.  Also, piping through more didn't work, but more was int he path.  Once I anaylzed the PATH and found the bogus dir I removed it and all was well again.  

Kandura:

I accepted you answer because I trust it would have fixed me regardless since it was platform independent making no external calls. I have needd this code snippet for other things.  Thanks for it.  I'm a perl beginner, any chance I could get you to disect it and elaborate on your code-comments me some more?


sub my_dir
{
     my $dir = shift;
     
     opendir(DIR, $dir) or die "Couldn't read dir $dir: $!";
     my @files = map { $_->[1] }                     # return filenames
               sort { $b->[0] <=> $a->[0] }             # sort on modification time
               map { [ -M "$dir/$_", $_] }                 # do a Schwartzian transform
               grep { !/^\.+$/ }                     # skip . and ..
               readdir(DIR);
     closedir DIR;

     @files;     # return as array
}


Cheers,
Scott



0
 
LVL 18

Expert Comment

by:kandura
ID: 9767670
Hi Scott,

I'll give it a try. Basically what I do is using readdir to get a list of entries in the specified directory.
The command to get the @files should be read backwards:
- readdir(DIR)
       this returns a list of all the entries in the directory
- grep { !/^\.+$/ }
        this removes all the files or directories whose name consists only of dots (usually just . and ..)
        it works by matching every element in the list returned by readdir to the given regexp,
        and only letting those through that do _not_ match (hence the !)

Now, the next bits are really just a fancy way to sort on the modification date. I'm using a Schwartzian Transform here
to optimize the sorting routine.
I could have just written the sort function in such a way that you compare the modification date for each pair, but I want to avoid
having to fetch the date again and again for each comparison. So what I do is prepare this before sorting: for every filename returned by
grep, I construct an anonymous array. The first element is the modification date, and the second is the original filename.
Now I can sort those anonymous arrays on the first element. You see that I only have to compare the pre-calculated values.
Finally, I return the original filename that was the second element in the anonymous arrays.
I've concatenated all those steps in one long command to avoid creating all kinds of temporary arrays (actually that is part of the Schwartzian Transform).

Let me write it out again, but in the right order, and with temp arrays:

my @all_files = readdir(DIR);                                                 # get all entries
my @grep_files = grep { ! /^\.+$/ } @all_files;                        # weed out . and ..
my @date_files = map { [ -M "$dir/$_", $_ ] } @grep_files;       # pre-calculate the modification dates
my @sort_dates = sort { $b->[0] <=> $a->[0] } @date_files;   # sort on the first entry in each [ ] array
my @sorted = map { $_->[1] } @sort_dates;                            # get only the filenames back
return @sorted;

As you can see, that is quite a bit longer and less efficient. Of course you can reuse a temp array, but this is for readability.
What the ST does, is eliminating all the assignments to the temporary arrays, by taking the output of one command as the input for the next.

Hope this clarifies it a bit :-)

Kandura
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

A year or so back I was asked to have a play with MongoDB; within half an hour I had downloaded (http://www.mongodb.org/downloads),  installed and started the daemon, and had a console window open. After an hour or two of playing at the command …
Checking the Alert Log in AWS RDS Oracle can be a pain through their user interface.  I made a script to download the Alert Log, look for errors, and email me the trace files.  In this article I'll describe what I did and share my script.
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now