We help IT Professionals succeed at work.

Windows Batch or VB script to return the directory holding a given file name

Hi,

There are over 1000 files in our shared drive / folder ;  though there's certain naming
convention, I still find it tough to trace which folder holds say a given filename.

Suppose I want a filename which has the term/text "contacts" in it (as I want to update
person's contact info of a Word Doc), I would normally do  at Windows MSDOS prompt :
a) dir/s z:\ > c:\temp\shdrv.txt
b) use Wordpad to search for the string "contacts"

Now, since I have a scheduled task to update shdrv.txt daily to my c:\temp
I'll need a script that could help me read the file shdrv.txt & then return all
the various occurrences of the filenames (with their date of creation/modification)
with the string "xxxxxxx" plus the directories that hold each of the filenames that
contain the string "xxxxxxx".

Using "find/I "string" shdrv.txt" returns the filenames but is missing on the
directories that hold the files
Comment
Watch Question

Meir RivkinFull stack Software Engineer

Commented:
change MATCH_TOKEN to whatever required.
the search is case-insensitive, to change it to case sensitive, set CASE_SENSITIVE to true.
const MATCH_TOKEN = "crypto"
const CASE_SENSITIVE = false
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objInputFile = objFSO.OpenTextFile("c:\temp\shdrv.txt", 1)

for each file in Split(objInputFile.ReadAll, vbCrLf)
	
	if MatchFileName(file) = true then
		Set objFile = objFSO.GetFile(file)
		Wscript.Echo "Name: " & objFile.Name
		Wscript.Echo "Date created: " & objFile.DateCreated
		Wscript.Echo "Date last accessed: " & objFile.DateLastAccessed
		Wscript.Echo "Date last modified: " & objFile.DateLastModified
		Wscript.Echo "Drive: " & objFile.Drive
		Wscript.Echo "Parent folder: " & objFile.ParentFolder
		Wscript.Echo "Path: " & objFile.Path
		Wscript.Echo "Short name: " & objFile.ShortName
		Wscript.Echo "Short path: " & objFile.ShortPath
		Wscript.Echo "Size: " & objFile.Size
		Wscript.Echo "Type: " & objFile.Type
		Wscript.Echo
	end if
Next

Function MatchFileName(file)

if CASE_SENSITIVE = false then
	MatchFileName = InStr(UCase(file), UCase(MATCH_TOKEN)) > 0 
else
	MatchFileName = InStr(file, MATCH_TOKEN) > 0 
end if

End Function

Open in new window

Peter KwanAnalyst Programmer

Commented:
strRootFolder = "Z:\"
str = "test"

Set objWshShell = WScript.CreateObject("WScript.Shell")
Set objFileSystem = WScript.CreateObject("Scripting.FileSystemObject")
Set objTxtFile = objFileSystem.CreateTextFile("C:\temp\temp.txt", True)
Set objRootFolder = objFileSystem.getFolder(strRootFolder)

FindFilesInFolder(objRootFolder)

objTxtFile.Close
Set objTxtFile = Nothing

Sub FindFilesInFolder(objFolder)
      For Each objFile in objFolder.Files
            If Instr(LCase(objFile.Name), str) Then
                  objTxtFile.WriteLine objFile.Name & "      " & objFolder.Path & 

"      " & objFile.DateLastModified
            End If
      Next

      For Each objSubFolder In objFolder.SubFolders
            FindFilesInFolder(objSubFolder)
      Next
End Sub

Peter KwanAnalyst Programmer
Commented:
Updated with minor mistake corrected:
strRootFolder = "Z:\"
str = "test"

Set objWshShell = WScript.CreateObject("WScript.Shell") 
Set objFileSystem = WScript.CreateObject("Scripting.FileSystemObject")
Set objTxtFile = objFileSystem.CreateTextFile("C:\temp\temp.txt", True)
Set objRootFolder = objFileSystem.getFolder(strRootFolder)

FindFilesInFolder(objRootFolder)

objTxtFile.Close
Set objTxtFile = Nothing

Sub FindFilesInFolder(objFolder)
	For Each objFile in objFolder.Files
		If Instr(LCase(objFile.Name), str) Then
			objTxtFile.WriteLine objFile.Name & "	" & objFolder.Path & "	" & objFile.DateLastModified
		End If
	Next

	For Each objSubFolder In objFolder.SubFolders
		FindFilesInFolder(objSubFolder)
	Next
End Sub

Open in new window

Commented:
another method

copy the code to notepad and save with vbs extension

change line 1 for file name and path to extrect data
line 2 folder to check for files

notice: the script will do the "dir" part for you and in the same time
will check if there is contacs in file name and extrect only the one that match

if the file not exist the script will create if exist the script will append to existing file

test and see
strFile = "c:\shdrv.txt"
objStartFolder = "c:\folder_to_check"

set objShell = CreateObject("wscript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
If Not objfso.FileExists(strFile) then
Set objlog = objfso.CreateTextFile(strFile,True)
Else
Set objlog = objfso.OpenTextFile(strFile,8)
End If

'objlog.WriteLine "Name" & vbTab & "Path" & vbTab & "DateCreated" & vbTab & "DateLastModified"

Set objFolder = objFSO.GetFolder(objStartFolder)
Set colFiles = objFolder.Files
For Each objFile in colFiles
    If InStr(objFile.Name,"contacts") Then 
            objlog.WriteLine objFile.Name & vbTab & objfile.Path & vbTab & objFile.DateCreated & vbTab & objfile.DateLastModified
    End if
Next
Wscript.Echo

ShowSubfolders objFSO.GetFolder(objStartFolder)

objlog.Close

objshell.Popup "done",5

Sub ShowSubFolders(Folder)
    For Each Subfolder in Folder.SubFolders
        Set objFolder = objFSO.GetFolder(Subfolder.Path)
        Set colFiles = objFolder.Files
        For Each objFile in colFiles
            If InStr(objFile.Name,"contacts") Then 
            objlog.WriteLine objFile.Name & vbTab & objfile.Path & vbTab & objFile.DateCreated & vbTab & objfile.DateLastModified
            End if
        Next
        Wscript.Echo
        ShowSubFolders Subfolder
    Next
End Sub

Open in new window

Commented:
forgot to remove something use this
strFile = "c:\shdrv.txt"
objStartFolder = "c:\folder_to_check"

set objShell = CreateObject("wscript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
If Not objfso.FileExists(strFile) then
Set objlog = objfso.CreateTextFile(strFile,True)
Else
Set objlog = objfso.OpenTextFile(strFile,8)
End If

'objlog.WriteLine "Name" & vbTab & "Path" & vbTab & "DateCreated" & vbTab & "DateLastModified"

Set objFolder = objFSO.GetFolder(objStartFolder)
Set colFiles = objFolder.Files
For Each objFile in colFiles
    If InStr(objFile.Name,"contacts") Then 
            objlog.WriteLine objFile.Name & vbTab & objfile.Path & vbTab & objFile.DateCreated & vbTab & objfile.DateLastModified
    End if
Next


ShowSubfolders objFSO.GetFolder(objStartFolder)

objlog.Close

objshell.Popup "done",5

Sub ShowSubFolders(Folder)
    For Each Subfolder in Folder.SubFolders
        Set objFolder = objFSO.GetFolder(Subfolder.Path)
        Set colFiles = objFolder.Files
        For Each objFile in colFiles
            If InStr(objFile.Name,"contacts") Then 
            objlog.WriteLine objFile.Name & vbTab & objfile.Path & vbTab & objFile.DateCreated & vbTab & objfile.DateLastModified
            End if
        Next
        ShowSubFolders Subfolder
    Next
End Sub

Open in new window

Meir RivkinFull stack Software Engineer

Commented:
@yehudaha, @pkwan

i might be wrong but according to @sunhux, the scheduler task already generates shdrv.txt contains list of all files which needed to be lookup for match string.
so no need to iterate files in folders etc.

>>I'll need a script that could help me read the file shdrv.txt & then return all the various occurrences of the file ...

see what @sunhux have to say about it...

Author

Commented:

Yes, sedgwick is right, I already have a scheduled job myself daily to generate shdrv.txt


Hi sedgwick,

What's  "const MATCH_TOKEN = "crypto"  "  for?
What other values I can change it to?  Sorry, I'm VB illiterate
Meir RivkinFull stack Software Engineer

Commented:
MATCH_TOKEN is the variable u want to change for the matched string.
if u look for "contact" in the files names, change the value of MATCH_TOKEN to "contact", simple as that.

the other value u can change is CASE_SENSITIVE.
the default (as u can see in the script) is false, which means that if you set MATCH_TOKEN to "contact" and the file name is ConTact123.txt, the script will output this file as well.
if you change this value to true, that means the search is case-sensitive and it look for exact phrase in the file name.
so ConTact123.txt will not be output by the script.
Meir RivkinFull stack Software Engineer

Commented:
sorry about the confusion, "crypto"  was just an example when i tested the script in my machine.

Commented:
so whats the probelm to run scheduled job on my script ?

all the work in one place insted to split it

Author

Commented:

When I ran Sedgwick's vbs script (I name it as filedir.vbs), I got "file not found"
I ran the script as follows :
d:\shareware\filedir.vbs "contact"



For Yehudaha's script, I need to pass the parameter "contacts" ie part of the file name
as parameter & not hardcode into the script  & the script should not need to search
the entire folder "objStartFolder = "z:\"   anymore as this is time-consuming/slow.
Just need to search c:\temp\shdrv.txt

Author

Commented:


Similar comments for pkwan's scripts (as mentioned for Yehudaha's script)

Author

Commented:

Oh, btw, since there's 3 VB experts in this thread, may I request all of you to take
a look at another EE thread  ID: 32791511  which is also VB related as the other
expert is now stuck
Meir RivkinFull stack Software Engineer

Commented:
@sunhux

i didn't say that u need to pass a parameter to the script.
the "contact" you wish to look, should be placed in the script itself (MATCH_TOKEN) as i explained in my previous post.

here's a modified script which accept parameter to look for in file names, so u can use either scripts.


const CASE_SENSITIVE = true
MATCH_TOKEN = Wscript.Arguments(0)
Wscript.Echo "Lookup token: " & MATCH_TOKEN
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objInputFile = objFSO.OpenTextFile("c:\temp\shdrv.txt", 1)

for each file in Split(objInputFile.ReadAll, vbCrLf)
	
	if MatchFileName(file) = true then
		Set objFile = objFSO.GetFile(file)
		Wscript.Echo "Name: " & objFile.Name
		Wscript.Echo "Date created: " & objFile.DateCreated
		Wscript.Echo "Date last accessed: " & objFile.DateLastAccessed
		Wscript.Echo "Date last modified: " & objFile.DateLastModified
		Wscript.Echo "Drive: " & objFile.Drive
		Wscript.Echo "Parent folder: " & objFile.ParentFolder
		Wscript.Echo "Path: " & objFile.Path
		Wscript.Echo "Short name: " & objFile.ShortName
		Wscript.Echo "Short path: " & objFile.ShortPath
		Wscript.Echo "Size: " & objFile.Size
		Wscript.Echo "Type: " & objFile.Type
		Wscript.Echo
	end if
Next

Function MatchFileName(file)

if CASE_SENSITIVE = false then
	MatchFileName = InStr(UCase(file), UCase(MATCH_TOKEN)) > 0 
else
	MatchFileName = InStr(file, MATCH_TOKEN) > 0 
end if

End Function

Open in new window

Meir RivkinFull stack Software Engineer

Commented:
the usage is as follow:

:\shareware\filedir.vbs "contact"

Commented:
hey

this will read your file from c:\temp\shdrv.txt
and output the directory with matching file name to the string to search

run from cmd for example:

cscript script_name.vbs contacts

where contacts is the string to search

you can change file location in line 13
If WScript.Arguments.Count = 0 Then
MsgBox "No Argument"
WScript.Quit
End If


Const ForReading = 1

Set objRegEx = CreateObject("VBScript.RegExp")
objRegEx.Pattern = WScript.Arguments.Item(0)

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("c:\temp\shdrv.txt", ForReading)

Do Until objFile.AtEndOfStream
strSearchString = objFile.ReadLine
if instr(strSearchString,"Directory") Then
strPath = strSearchString
End If
    Set colMatches = objRegEx.Execute(strSearchString)  
    If colMatches.Count > 0 Then
        For Each strMatch in colMatches
            WScript.Echo strPath   
            Wscript.Echo strSearchString 
            WScript.Echo
        Next
    End If

Loop

objFile.Close

Open in new window

Meir RivkinFull stack Software Engineer

Commented:
@sunhux

>>a look at another EE thread  ID: 32791511  which is also VB related as the other
can u post the link to the thead?

Author

Commented:

sedgwick's script still has an error :
I ran it as follows:
  d:\shareware\filedir.vbs "contact"
It 1st gave a popup saying "Lookup token : contact" & after I click OK,
it gave a "File not found" error popup indicating Line 10, Char 3 :
see attached screen shot


Just to illustrate what I wanted using find command,

D:\shareware>find/I "contact" c:\temp\shdrv.txt | more
---------- C:\TEMP\SHDRV.TXT
10/15/2007  06:36 PM           491,008 Update Subcontractor Leave Contact Number.doc
12/01/2008  11:01 AM            76,288 Contact List 01122008_v28.0.xls
. . .

So what I wanted your VB scripts to do is to list out the following outputs:

Directory of Z:\Operations\Vendors\
10/15/2007  06:36 PM           491,008 Update Subcontractor Leave Contact Number.doc

Directory of Z:\DR\Year2008
12/01/2008  11:01 AM            76,288 Contact List 01122008_v28.0.xls



Will test yehudaha's script
Filedirerrscrdmp.doc

Author

Commented:

yedudaha's script works fine.


Anybody care to take up another challenge in another post which I've put up :
... may I request all of you to take a look at another EE thread  ID: 32791511
  which is also VB related as the other expert is now stuck

Author

Commented:

Oh, I just realize Yedudaha's script search for a case-sensitive string (say "contact").

Care to make it case-insensitive ?

Commented:
glad it helped don't forget to close the question :-)

and post the full link to your question
Commented:
here
If WScript.Arguments.Count = 0 Then
MsgBox "No Argument"
WScript.Quit
End If


Const ForReading = 1

Set objRegEx = CreateObject("VBScript.RegExp")
objRegEx.IgnoreCase = true
objRegEx.Pattern = WScript.Arguments.Item(0)

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\shdrv.txt", ForReading)

Do Until objFile.AtEndOfStream
strSearchString = objFile.ReadLine
if instr(strSearchString,"Directory") Then
strPath = strSearchString
End If
    Set colMatches = objRegEx.Execute(strSearchString)  
    If colMatches.Count > 0 Then
        For Each strMatch in colMatches
            WScript.Echo strPath   
            Wscript.Echo strSearchString 
            WScript.Echo
        Next
    End If

Loop

objFile.Close

Open in new window

Meir RivkinFull stack Software Engineer

Commented:
@sunhux

the reason of the error is because the file it tried to open is not accessible.
if the only thing u need is compare the file name + log the parent directory, use the following script.


const CASE_SENSITIVE = true
const SOURCE_FILE = "c:\temp\shdrv.txt"
MATCH_TOKEN = Wscript.Arguments(0)

Wscript.Echo "Source file: " & SOURCE_FILE
Wscript.Echo "Lookup token: " & MATCH_TOKEN

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objInputFile = objFSO.OpenTextFile(SOURCE_FILE, 1)

Do Until objInputFile.AtEndOfStream
	file = objInputFile.ReadLine	
	
	if MatchFileName(file) = true then
		path = Mid(file, 1, InStrRev(file, "\"))
		fileName = Replace(file,path,"")
		Wscript.Echo "Directory of " & path
		Wscript.Echo Date & " " & Time & " " & fileName
		
	end if
Loop

objInputFile.Close

Function MatchFileName(file)

if CASE_SENSITIVE = false then
	MatchFileName = InStr(UCase(file), UCase(MATCH_TOKEN)) > 0 
else
	MatchFileName = InStr(file, MATCH_TOKEN) > 0 
end if

End Function

Open in new window

Meir RivkinFull stack Software Engineer

Commented:
the output is in the form u requested.
btw, what is the meaning of the number preceeding the file name in your example?

Directory of Z:\DR\Year2008
12/01/2008  11:01 AM            76,288 Contact List 01122008_v28.0.xls

what 76,288 refer to??
Meir RivkinFull stack Software Engineer
Commented:
i modified the script to sort the files based on the directory for better result output.
so the output should look like:

Directory1
Date Time FileA
Date Time FileB
Date Time FileC

Directory2
Date Time FileD
Date Time FileE

for example check the testing txt log attached.


const CASE_SENSITIVE = true
const SOURCE_FILE = "c:\temp\shdrv.txt"
MATCH_TOKEN = Wscript.Arguments(0)

Wscript.Echo "Source file: " & SOURCE_FILE
Wscript.Echo "Lookup token: " & MATCH_TOKEN

Set dict = CreateObject("Scripting.Dictionary")

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objInputFile = objFSO.OpenTextFile(SOURCE_FILE, 1)

Do Until objInputFile.AtEndOfStream
	file = objInputFile.ReadLine	
	
	if MatchFileName(file) = true then
		path = Mid(file, 1, InStrRev(file, "\"))
		fileName = Replace(file,path,"")
	
		if dict.Exists(path) then
			dict(path) = dict(path) & "," & fileName
		else
			dict(path) = fileName
		end if
	end if
Loop

objInputFile.Close

ShowResults

Sub ShowResults

for each key in dict.Keys
	Wscript.Echo
	Wscript.Echo "Directory of " & key
	for each file in Split(dict(key),",")
		Wscript.Echo Date & " " & Time & " " & file	
	Next
Next

End Sub

Function MatchFileName(file)

if CASE_SENSITIVE = false then
	MatchFileName = InStr(UCase(file), UCase(MATCH_TOKEN)) > 0 
else
	MatchFileName = InStr(file, MATCH_TOKEN) > 0 
end if

End Function

Open in new window

testing.txt

Author

Commented:

Both sedgwick & yedudaha's latest scripts work as per what I needed.

Thanks

Author

Commented:

Ok, next, can someone take a look at the next issue I have at the following link:

http://www.experts-exchange.com/Programming/Languages/Visual_Basic/VB_Script/Q_26194745.html


Thanks
Meir RivkinFull stack Software Engineer

Commented:
please first close this thread.

cheers