[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 487
  • Last Modified:

Need a script that will grab the contents of a directory tree and throw it into an html page.

Hi,

  Not sure how to go about this, but what I want to do is execute a script or program that will grab all the contents from a directory tree and plug it into an html format, sort of like a table of contents.  The thing is, the directory tree is going to be updated a few times a week, so I just want to fire off this script or program that will update the html page.  This is in a windows environment.

Is this do-able?


pete
0
pskreb
Asked:
pskreb
  • 12
  • 8
  • 6
  • +1
3 Solutions
 
Lee W, MVPTechnology and Business Process AdvisorCommented:
Sure, I take it you want the directories to be linked?

0
 
Lee W, MVPTechnology and Business Process AdvisorCommented:
To make this easier, I'd probably make a single HTML file that "includes" the contents of the constructed HTML file.  Does your web server support server side includes (SSI)?
0
 
Lee W, MVPTechnology and Business Process AdvisorCommented:
@echo off
If exist dir.html del dir.html
for /f "tokens=*" %%a in ('dir /ad /b') do echo ^<a href="./%%a"^>%%a^</a^> >> dir.html




If you can't use server side includes then you can either setup a "top.html" file and a "bottom.html" file and combine top+dir+bottom into one.  

And of course, yet another solution, you can turn directory browsing on and people will just see the directory structure.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
pskrebAuthor Commented:
1.  Yes, I want the directories to be linked
2.  The directory tree is located on a Windows server, in a standard NT directory structure.
3.  Let's say the directory and subfiles are at //joe/workgroups/eng/directory
   and I want to display this in an html file called Directory_contents.html located on //joe/workgroups/eng

not sure if the server supports SSI.

pete
0
 
Lee W, MVPTechnology and Business Process AdvisorCommented:
If you're using IIS, then it should.  If it's IIS, I really would just enable directory browsing. Much easier.

The paths you listed above are unix like - do you mean joe is the computer name, workgroups the share name, then eng/directory are directories?  Assuming that to be the case,

That said, I THINK this will work for you:

@echo off
set dirpaths=\\joe\workgroups\eng\directory
If exist %dirpaths%\dir.html del %dirpaths%\dir.html
for /f "tokens=*" %%a in ('dir %dirpaths% /ad /b') do echo ^<a href="./%%a"^>%%a^</a^> >> dir.html


You may have to tweak the href path...
0
 
pskrebAuthor Commented:
Okay, what if I'm not running IIS or any local webserver, but I still want to dump this information into an htmli html page that I can bring up in a browser?
0
 
pskrebAuthor Commented:
Actually, to answer your question, I saw the entry was backwards.  It's actually \\joe\workgrps\eng\directory, where "joe" is the name of the server and the directories beneath just lead to the directory that has my data in it.

I got it to work, but it just shows the directory names on top of the dir.html.  I was hoping to have an all-inclusive html document that lists ALL the contents of each directory on one html page, sort of like a table of contents, with each file being linkable.  Most of the files are .doc files, some are .xls files.

0
 
Lee W, MVPTechnology and Business Process AdvisorCommented:
You're not running a web server?  Without a web server your just looking at files.   You might be able to do it... I have some vague ideas of ways it might work, but I've always used web servers.  Any reason you're not using a web server for this?  Will this web page be accessed externally or internally or both?
0
 
Lee W, MVPTechnology and Business Process AdvisorCommented:
Who will be accessing the files and what kind of files are they.  Understanding this may help me/us better understand what you want to accomplish.  In addition, please answer the previous questions.
0
 
pskrebAuthor Commented:
The files will be accessed internally only, by a small group of people.  Like I said before, they're .doc and .xls files.   All I really wanted to do was create a 'table of contents' sort of file that would list the directories and all the files within the directories.  This html file is eventually going to be put into a website, but for now I just wanted it to be a standalone html file that lists this information.  

We might be running IIS on the //joe server, not sure.  How do I find out?

thanks!!

pete
0
 
Lee W, MVPTechnology and Business Process AdvisorCommented:
I'll need some time on this - or perhaps someone else will come along.  

IIS comes with NT4 Option Pack, 2000 Server (all version), 2003 server (all versions).  Most of it's functionality is disabled by default in 2003.  Is there a directory on your server C:\inetpub?  If so, then you have at least SOME IIS components installed - or did at one time.
0
 
pskrebAuthor Commented:
I don't see an \inetpub at the root (\\joe) directory.  That's as far as I can tell.  

0
 
FishMongerCommented:
A simple "DOS" directory listing inserted into html links won't work.  Your best solution is to use a Perl CGI script which will scan/parse the dirs, and dynamicly create the html page.  Doing so will allow you to add/remove files as often as you wish without needing to recreate a static html file everytime you make a change.  This also means that you'll need to install a web server, such as IIS or Apache.  I've used both, but my preference is Apache; it's free and  compared to IIS it's more stable and secure.

http://httpd.apache.org/

Post a 20 point question in the Perl topic area pointing to this Q and if I can't post soon enough (my schedule is very tight these days), one of the others will be able to provide you with what you need.
0
 
fahimnxbCommented:
COMPLETE CODE IN VB.NET

Imports System
Imports System.IO
Imports System.Collections

Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call

    End Sub

    'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    Friend WithEvents OpenFileDialog1 As System.Windows.Forms.OpenFileDialog
    Friend WithEvents Button1 As System.Windows.Forms.Button
    Friend WithEvents btnGenerate As System.Windows.Forms.Button
    Friend WithEvents Panel1 As System.Windows.Forms.Panel
    Friend WithEvents txtCode As System.Windows.Forms.TextBox
    Friend WithEvents Label1 As System.Windows.Forms.Label
    Friend WithEvents Label2 As System.Windows.Forms.Label
    Friend WithEvents Label3 As System.Windows.Forms.Label
    Friend WithEvents txtPath As System.Windows.Forms.TextBox
    Friend WithEvents txtFolder As System.Windows.Forms.TextBox
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.OpenFileDialog1 = New System.Windows.Forms.OpenFileDialog()
        Me.txtPath = New System.Windows.Forms.TextBox()
        Me.Button1 = New System.Windows.Forms.Button()
        Me.btnGenerate = New System.Windows.Forms.Button()
        Me.Panel1 = New System.Windows.Forms.Panel()
        Me.txtCode = New System.Windows.Forms.TextBox()
        Me.Label1 = New System.Windows.Forms.Label()
        Me.Label2 = New System.Windows.Forms.Label()
        Me.txtFolder = New System.Windows.Forms.TextBox()
        Me.Label3 = New System.Windows.Forms.Label()
        Me.Panel1.SuspendLayout()
        Me.SuspendLayout()
        '
        'txtPath
        '
        Me.txtPath.ForeColor = System.Drawing.SystemColors.Window
        Me.txtPath.Location = New System.Drawing.Point(48, 8)
        Me.txtPath.Name = "txtPath"
        Me.txtPath.ReadOnly = True
        Me.txtPath.Size = New System.Drawing.Size(352, 20)
        Me.txtPath.TabIndex = 0
        Me.txtPath.Text = ""
        '
        'Button1
        '
        Me.Button1.Location = New System.Drawing.Point(408, 8)
        Me.Button1.Name = "Button1"
        Me.Button1.Size = New System.Drawing.Size(32, 20)
        Me.Button1.TabIndex = 1
        Me.Button1.Text = "......"
        '
        'btnGenerate
        '
        Me.btnGenerate.Location = New System.Drawing.Point(368, 280)
        Me.btnGenerate.Name = "btnGenerate"
        Me.btnGenerate.TabIndex = 2
        Me.btnGenerate.Text = "Generate...."
        '
        'Panel1
        '
        Me.Panel1.BackColor = System.Drawing.Color.AliceBlue
        Me.Panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
        Me.Panel1.Controls.AddRange(New System.Windows.Forms.Control() {Me.txtFolder, Me.Label1, Me.txtCode, Me.btnGenerate, Me.txtPath, Me.Button1, Me.Label2, Me.Label3})
        Me.Panel1.Location = New System.Drawing.Point(8, 8)
        Me.Panel1.Name = "Panel1"
        Me.Panel1.Size = New System.Drawing.Size(464, 312)
        Me.Panel1.TabIndex = 3
        '
        'txtCode
        '
        Me.txtCode.Location = New System.Drawing.Point(48, 80)
        Me.txtCode.Multiline = True
        Me.txtCode.Name = "txtCode"
        Me.txtCode.ReadOnly = True
        Me.txtCode.Size = New System.Drawing.Size(400, 192)
        Me.txtCode.TabIndex = 3
        Me.txtCode.Text = ""
        '
        'Label1
        '
        Me.Label1.Location = New System.Drawing.Point(8, 12)
        Me.Label1.Name = "Label1"
        Me.Label1.Size = New System.Drawing.Size(32, 16)
        Me.Label1.TabIndex = 4
        Me.Label1.Text = "Path:"
        '
        'Label2
        '
        Me.Label2.Location = New System.Drawing.Point(8, 40)
        Me.Label2.Name = "Label2"
        Me.Label2.Size = New System.Drawing.Size(40, 16)
        Me.Label2.TabIndex = 4
        Me.Label2.Text = "Folder:"
        '
        'txtFolder
        '
        Me.txtFolder.Location = New System.Drawing.Point(48, 40)
        Me.txtFolder.Name = "txtFolder"
        Me.txtFolder.Size = New System.Drawing.Size(400, 20)
        Me.txtFolder.TabIndex = 5
        Me.txtFolder.Text = ""
        '
        'Label3
        '
        Me.Label3.Location = New System.Drawing.Point(8, 80)
        Me.Label3.Name = "Label3"
        Me.Label3.Size = New System.Drawing.Size(32, 16)
        Me.Label3.TabIndex = 4
        Me.Label3.Text = "Code:"
        '
        'Form1
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.BackColor = System.Drawing.SystemColors.InactiveCaptionText
        Me.ClientSize = New System.Drawing.Size(480, 326)
        Me.Controls.AddRange(New System.Windows.Forms.Control() {Me.Panel1})
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.Panel1.ResumeLayout(False)
        Me.ResumeLayout(False)

    End Sub

#End Region

    Dim path As String
    Dim sb As FileStream
    Dim sw As StreamWriter

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    End Sub


    ' Process all files in the directory passed in, and recurse on any directories
    ' that are found to process the files they contain
    Public Sub ProcessDirectory(ByVal targetDirectory As String)
        Dim fileEntries As String() = Directory.GetFiles(targetDirectory)
        ' Process the list of files found in the directory        
        Dim fileName As String
        sw.Write("<table>")
        txtCode.Text = "<table>"
        For Each fileName In fileEntries
            ProcessFile(fileName)
            sw.WriteLine("<tr><td><a href='" & txtFolder.Text & fileName.Substring(path.Length + 1) & "' target='_blank'>" & fileName.Substring(path.Length + 1) & "</a></td></tr>")
            txtCode.Text = txtCode.Text & "<tr><td><a href='" & txtFolder.Text & fileName.Substring(path.Length + 1) & "' target='_blank'>" & fileName.Substring(path.Length + 1) & "</a></td></tr>"
        Next fileName
        sw.Write("</table>")
        txtCode.Text = txtCode.Text & "<table>"
        sw.Close()
        'Dim subdirectoryEntries As String() = Directory.GetDirectories(targetDirectory)
        '' Recurse into subdirectories of this directory
        'Dim subdirectory As String
        'For Each subdirectory In subdirectoryEntries
        '    ProcessDirectory(subdirectory)
        'Next subdirectory

    End Sub 'ProcessDirectory

    ' Real logic for processing found files would go here.
    Public Sub ProcessFile(ByVal path As String)
        'MsgBox("Processed file " & path)
    End Sub 'ProcessFile


    Private Sub btnGenerate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGenerate.Click
        sb = New FileStream(path & "\MyFile.html", FileMode.OpenOrCreate)
        sw = New StreamWriter(sb)

        If File.Exists(path) Then
            ' This path is a file
            ProcessFile(path)
        Else
            If Directory.Exists(path) Then
                ' This path is a directory
                ProcessDirectory(path)
            Else
                MsgBox(path & " is not a valid file or directory.")
            End If
        End If
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        If OpenFileDialog1.ShowDialog() = DialogResult.OK Then
            txtPath.Text = OpenFileDialog1.FileName().Substring(0, OpenFileDialog1.FileName().LastIndexOf("\"))
            path = txtPath.Text
        End If
    End Sub
End Class


Regards,
me
0
 
Lee W, MVPTechnology and Business Process AdvisorCommented:
WOW... that's a lot of coding.  I'll be looking things over tomorrow, but there's I don't think theres a need for a script that long.  I'm fairly certain using good 'ol reliable batch commands this can be done in about 10-15 lines.
0
 
fahimnxbCommented:
Ya leew u r right the actual code is really of 15 or max 20 lines, I just copy pasted the complete designer generated code here, so that its easy for "pskreb" to use.

However after ur comment I decided to ;) put the needed code again. Here it is....


' Process all files in the directory passed in, and recurse on any directories
 ' that are found to process the files they contain

    Public Sub ProcessDirectory(ByVal targetDirectory As String)
        Dim fileEntries As String() = Directory.GetFiles(targetDirectory)
        ' Process the list of files found in the directory        
        Dim fileName As String
        sw.Write("<table>")
        txtCode.Text = "<table>"
        For Each fileName In fileEntries
            ProcessFile(fileName)
            sw.WriteLine("<tr><td><a href='" & txtFolder.Text & fileName.Substring(path.Length + 1) & "' target='_blank'>" & fileName.Substring(path.Length + 1) & "</a></td></tr>")
            txtCode.Text = txtCode.Text & "<tr><td><a href='" & txtFolder.Text & fileName.Substring(path.Length + 1) & "' target='_blank'>" & fileName.Substring(path.Length + 1) & "</a></td></tr>"
        Next fileName
        sw.Write("</table>")
        txtCode.Text = txtCode.Text & "<table>"
        sw.Close()
        'Dim subdirectoryEntries As String() = Directory.GetDirectories(targetDirectory)
        '' Recurse into subdirectories of this directory
        'Dim subdirectory As String
        'For Each subdirectory In subdirectoryEntries
        '    ProcessDirectory(subdirectory)
        'Next subdirectory

    End Sub 'ProcessDirectory

    Private Sub btnGenerate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGenerate.Click
        sb = New FileStream(path & "\MyFile.html", FileMode.OpenOrCreate)
        sw = New StreamWriter(sb)

        If File.Exists(path) Then
            ' This path is a file
        Else
            If Directory.Exists(path) Then
                ' This path is a directory
                ProcessDirectory(path)
            Else
                MsgBox(path & " is not a valid file or directory.")
            End If
        End If
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        If OpenFileDialog1.ShowDialog() = DialogResult.OK Then
            txtPath.Text = OpenFileDialog1.FileName().Substring(0, OpenFileDialog1.FileName().LastIndexOf("\"))
            path = txtPath.Text
        End If
    End Sub


Regards,
me
0
 
pskrebAuthor Commented:
So this is VB code, eh?  I suppose it needs to be compiled.  How do I go about doing that?  What should be the end result, an executable file?

pete
0
 
pskrebAuthor Commented:
Tried saving the shorter version as a .vbs and compiling with cscript and got:

(4, 55) Microsoft VBScript compilation error:  Expected ')'


Tried saving the longer version as a .vbs and compiling with cscript and got:

(5, 8) Microsoft VBScript compilation error:  Expected Identifier
 
0
 
fahimnxbCommented:
Its VB.NET code...

me
0
 
pskrebAuthor Commented:
Okay, I guess I don't know how to handle "VB.NET code".


Do I need VB.NET Visual Studio?  
How can I get this code to work for me?


pete
0
 
pskrebAuthor Commented:
Not sure where to go from here.
0
 
FishMongerCommented:
Even though it is possible, tring to do what you want without a web server is a waste of time.  Just share the directory that the files are in and use Network Neighborhood or Windows Explorer.  The users can put a shortcut on their desktop that takes them directly to that shared directory.

If you really want an Intranet web page/site, install the web server of your choice and (with our help) write either a php or Perl script that will dynamicaly create the page(s).  There isn't any good reason to have a script that you routinely need to execute just to create a static html file.
0
 
pskrebAuthor Commented:
Okay,

  So let's say I'll run a webserver, since I already have Apache and Tomcat installed.  What would a Perl page that does this type of display, look like?

0
 
FishMongerCommented:
>> What would a Perl page that does this type of display, look like?

I'm not sure what you mean.  The look of the page has more to do with what html elements you want to use and the use of css (cascading style sheets) and javascript.  In this case Perl's main function is to scan the directories looking for the doc & xls files and create links to them; it;s up to you to decide how you want the page to look.

These next 2 weeks are my busiest of the year, but I'll try to find some time to work up a short script.
0
 
pskrebAuthor Commented:
very simple listing:


Columns:

Directory name
name of document             location          date last modified
...


Directory name
name of document             location         date last modified
...

etc., etc.

(and it would be cool if each document was linked to its location)

0
 
FishMongerCommented:
Due to by schedule, it may take me a little time to test/debug the script but in the mean time, here's the "skeleton" of the script.  If you're not familar with Perl, I'd recommend picking up at least one book.

   http://www.oreilly.com/catalog/lperl3/
and/or
   http://www.oreilly.com/catalog/perlnut2/


#!c:/perl/bin/perl -w

use strict;
use CGI;
use File::Find;

my $dir = 'path/to/base/dir';

# output HTML headers
# start table

# scan the directories and build the links
find(\&build_links, $dir);

# end table
# closing HTML tags



sub build_links {

   if (-d) {
      print "<tr><td>$File::Find::dir</td></tr>\n";
   }

   else {

      # my $url_encoded_file = encode the path/filename
      # my $mtime;

      print "<tr><td>$url_encoded_file</td>\n",
            "<td>$File::Find::name</td>\n",
            "<td>$mtime</td></tr>\n";
   }
}
0
 
pskrebAuthor Commented:
Jeez, what if I don't want to use Perl because of the overhead.

How about .js or .vbs or even RUBY!

sorry about being a pain.

pete
0
 
FishMongerCommented:
Overhead will be very close between them and my bet is that Perl would be the fastest (especially if it's run with Mod/Perl and apache), also Perl will have the cleanest and shortest code especially when compared to vbs or the VB.NET code that pskreb provided.  Perl cgi scripts run the majority of the web sites with PHP following close behind.  A Perl script of this nature would only take a fraction of a second to scan the directories and build/output the web page.  Another advantage to Perl is that it's platform independant.

If you don't want to use Perl, then you should use the language that you know best and as long as you code it properly, you should not need to worry too much about the overhead.
0
 
FishMongerCommented:
Since I've been "house sitting" for some freinds and their system doesn't have Perl or Apache, I haven't been able to properly test/debug the script so this may need a little tweeking.


#!c:/perl/bin/perl.exe -w

use strict;
use CGI qw/:standard/;
use CGI::Carp 'fatalsToBrowser';
use URI::file;
use File::Find;

my %dir;
my $dir = 'c:/temp';

print header,
      start_html('xls and doc files'),
      '<table border=2>';

find(\&build_links, $dir);

print '</table>',
      end_html;



sub build_links {

   if (-d) {
      print "\n<tr><td colspan=3>$File::Find::dir</td></tr>\n" unless $dir{$File::Find::dir};
      $dir{$File::Find::dir}++;
   }

   else {

      my $path = URI::file->new( $File::Find::name );
      $path =~ s!c:!cgi-bin/../../../..!i;
      my $mtime = localtime((stat($File::Find::name))[9]);

      print "\n<tr>\n",
            "\t<td><a href=$path>$_</a></td>\n",
            "\t<td>$File::Find::name</td>\n",
            "\t<td>$mtime</td>\n",
            "\n</tr>\n";
   }
}
0

Featured Post

Prep for the ITIL® Foundation Certification Exam

December’s Course of the Month is now available! Enroll to learn ITIL® Foundation best practices for delivering IT services effectively and efficiently.

  • 12
  • 8
  • 6
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now