Link to home
Start Free TrialLog in
Avatar of Rocutana Rim
Rocutana Rim

asked on

Lists all the files in a folder and output as "FolderName.csv" file for each Parent folder.

I am using this code, But I want to modify such that the output should be separate csv files for each parent folder. i.e if a computer has 2 drives c & d I require C_Output.csv, D_Output.csv. I am using this to list files in a server path. I want my output as foldername.csv...If this is not possible, can I get a modification for below script to list all the files for a folder output as foldername.csv and run again to next folder and so on.



Dim fso
Dim ObjOutFile

Set fso = CreateObject("Scripting.FileSystemObject")

Set ObjOutFile = fso.CreateTextFile("OutputFiles.csv")

ObjOutFile.WriteLine("Type,File Name,File Path")

GetFiles("MyLocation")

ObjOutFile.Close

WScript.Echo("Completed")

Function GetFiles(FolderName)
    On Error Resume Next

    Dim ObjFolder
    Dim ObjSubFolders
    Dim ObjSubFolder
    Dim ObjFiles
    Dim ObjFile

    Set ObjFolder = fso.GetFolder(FolderName)
    Set ObjFiles = ObjFolder.Files

    For Each ObjFile In ObjFiles
    ObjOutFile.WriteLine("File," & ObjFile.Name & "," & ObjFile.Path)
    Next

    Set ObjSubFolders = ObjFolder.SubFolders

    For Each ObjFolder In ObjSubFolders

        ObjOutFile.WriteLine("Folder," & ObjFolder.Name & "," & ObjFolder.Path)


        GetFiles(ObjFolder.Path)
    Next

End Function

Open in new window

Avatar of Karrtik Iyer
Karrtik Iyer
Flag of India image

In your main code, call getfiles for each drive. Psuedo code below.
//First get the collection of drives
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set colDrives = objFSO.Drives

For Each objDrive in colDrives
    Wscript.Echo "Drive letter: " & objDrive.DriveLetter
    Set ObjOutFile = fso.CreateTextFile(objDrive.DriveLetter & "_" &"OutputFiles.csv")
     ObjOutFile.WriteLine("Type,File Name,File Path")
    GetFiles(objDrive.driveLetter) //Or there could be obDrive.DriveName, please check documentation
    ObjOutFile.Close
Next

Open in new window

Avatar of Bill Prew
Bill Prew

Can you describe a little further what results you want?  Are you reporting all files on each entire drive, or just one particular folder that will exist on all drives?  What if the same folder name exists on two drives, as it stands there is only one file for that folder name?

For example, if you have the following two drives, and folders, and files, what info would you want in what named files output by the script?

DRIVE = C:
  FOLDER = C:\TEMP
    FILE = C:\TEMP\FILE1.TXT
    FILE = C:\TEMP\FILE1.TXT
DRIVE = D:
  FOLDER = D:\TEMP
    FILE = D:\TEMP\FILE1.TXT
    FILE = D:\TEMP\FILE1.TXT

~bp
Avatar of Rocutana Rim

ASKER

@Karrtik Iyer - Thank you for your suggestion but I don't want for drives in a computer but folders in a server. I will try to work with your suggestion and report the result.

@Bill Prew - Thank you for your response.
I want a report of all the files in a drive but the output should be separate for each drive as I am taking the list of files in server and it will take very long time as it includes thousands of files and folders of diifrent formats like images, pdfs etc. So I want the output for each folder separately. I should be able to run the script and specify the output folder and the script should save the output for each separately.
In that case, you mean say you shall be querying path like \\somecomp1\somefolder.
And for files present in this remote location you want whether these files is on C drive or D drive on the remote computer?
Say you get a file called somefile.txt in the location \\somecomp1\somefolder, you want to find out if this somefile.txt is on C or D drive in the somecomp1 and based on that create a output CSV file?
@Karrtik Iyer - No, I want list of all files in server but output should be for each folder as it will take very long time and may be difficult to open csv and may become very large, it includes thousands of files and folders of different formats like images, pdfs etc.
Ok, I get it now, I got confused because of your below comment:
i.e if a computer has 2 drives c & d I require C_Output.csv, D_Output.csv
Thanks Karrtik Iyer - I gave that as an example, if I run it to local computer I require the list for each drive separately. can you modify my above code to perform to my requirement.
Before that, if you have a server folder, \\server\root_folder
and in root_folder --> has files A.txt, B.txt and another folder Folder1 and Folder 2
Folder 1 has C.txt and D.txt and another sub folder Folder 1_1
And folder1_1 has E.txt and F.txt.
And folder 2 has G.txt and H.txt
It looks like:
root_folder
        A.txt
        B.txt
        Folder1
                  C.txt
                   D.txt
                   Folder1_1
                               E.txt
                               F.txt
        Folder2
                   G.txt
                   H.txt

What would be your expected output? How many output files shall be created and what shall each one contain?
Here are my suggestions: (if you want the output files to be created only for the subfolders inside the root folder (the server path) and not recursively
1> Get subfolders in the serverpath
2> In a for loop for each folder create output file foldername_output.csv
3> then for each file inside your subfolder (say A), call getfile function of yours , but you shall have to modify your getfile function to get all the files recursively even from all sub folders inside this folder A.
4> close the file handle
Below is the pseudo code.
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set rootfolder= objFSO .GetFolder("MyServerLocation")
Set subfolders= f.SubFolders
For Each subfolder in subfolders
    Set ObjOutFile = objFSO .CreateTextFile(subfolder.Name & "_" &"OutputFiles.csv")
     ObjOutFile.WriteLine("Type,File Name,File Path")
    GetFiles(subfolder.Name) //Make (change code) sure this getfiles function queries for all the files recursively for more folders inside this subfolder.
Next

Open in new window

@Karrtik Iyer - Actually in the server we have multiple folders of different projects and are shared. eg- \\server1\project 1, \\server1\project 2 etc. I want to run the script from my local computer with server name "server 1" as start folder and the outputs to be list of all files in the project folders i.e. project 1_list.csv, project 2_list.csv. Hope I am clear to you now.
So @Vijayendra, my last comment is the solution to your problem, it shall get all folders (project1, project2,etc..) inside your "MyserverLocation". And then call get files on it with the folder name(project1, project2,etc...) for each folder inside your server location. And it shall create output file name called project1_output.csv,etc..
But your get files function has to be modified to fetch all other files inside  sub folders that might exist inside project1. Currently it shall only fetch files directly under each project (project1), but it shall not fetch a file if it can exist below some sub folders of project1 say project1\subfolder1\a.txt. If this case will never happen then your get files function is fine.
Here is the code again, in the earlier piece (last comment) I had forgotten to close the file handle.
[code]
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set rootfolder= objFSO .GetFolder("MyServerLocation")
Set subfolders= rootfolder.SubFolders
For Each subfolder in subfolders
    Set ObjOutFile = objFSO .CreateTextFile(subfolder.Name & "_" &"OutputFiles.csv")
     ObjOutFile.WriteLine("Type,File Name,File Path")
    GetFiles(subfolder.Name) //Make (change code) sure this getfiles function queries for all the files recursively for more folders
inside this subfolder.
     ObjOutFile.Close
Next
[/code]
In case your \\server1\project1 can contain further sub folders, and you want your getfiles to list those files as well in project1_output.csv then you shall have to use recursion inside your getfiles function to fetch the file list inside those subfolders as well. Something like below.
I am staying away from modifying your getfiles function and give you a direct solution since we want you try out and understand the solution. Hence giving your pointers to implement it yourself.
Sub DisplaySubFolders(Folder)
    For Each folder in Folder.SubFolders
        Wscript.Echo folder.Path
        Set objFolder = objFSO.GetFolder(folder.Path)
        Set listofFiles = objFolder.Files
        For Each file in listofFiles 
            Wscript.Echo file.Name
        Next
        Wscript.Echo
        DisplaySubFolders folder
    Next
End Sub

Open in new window

@Karrtik Iyer - Actually in the server we have multiple folders of different projects and are shared. eg- \\server1\project 1, \\server1\project 2 etc. I want to run the script from my local computer with server name "server 1" as start folder and the outputs to be list of all files in the project folders i.e. project 1_list.csv, project 2_list.csv. Hope I am clear to you now.
Are there subfolders under each project, and if so how are they to be handled?  Do you want all files from the project in all subfolders in a single project CSV?

~bp
@Bill Prew - Yes, I want all the files in all sub folders of a project in a single csv. For 1 project there should be 1 output csv file and should contain all list of files. The script above gives the output for single folder and each time I have to change the path and run.
@vijayendra, did you try modifying the script as per my last but one comment(second last) and test it?
For getting the files below project1 sub folders did you make your getfiles function recursive and test as per my last comment?
@Karrtik Iyer, I tried modifying the script as per your comment but I am getting error in line 4 character 27 as "Expected end of statement" and since I am a beginner and can not modify the script more. Thanks for your reply.
Can you post the latest modified script so that we can help you with the error?
SOLUTION
Avatar of Karrtik Iyer
Karrtik Iyer
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi Karrtik Iyer - Thanks for your suggestions and link, I will use and implement your suggestions. You have given detailed comments in your code and I am thankful to you. your code works great.

@Bill Prew - Thanks for your code. it works great and to my requirements.

Once again I thank both of you for your help.

But I have one question regarding this - If I run on my D Drive it gives me "Permission Denied" error. This has something to do with the RECYCLE.BIN which is invisible. The file is formed as "$RECYCLE.BIN_OutputFiles" but it has no information.
I added "On Error resume next" and the script is running.

But Is there any option which can list the files/folders which gives any errors while running.

Thank You
Hi vijayendra, can I know why the vbscript that I attached is not selected as the answer? What are the problems in it as compared to bill prew 's answer?
@Bill Prew - Also can you add a line of code so that if any files are directly in the server location, it can be listed. Karrtik Iyer has given this in his code but I am unable to add it in your code.

I tried changing objRootFolder to strBaseDir as this is the object in your file but it gives error.

set ObjOutFile = objFSO.CreateTextFile(objRootFolder.Name & "_" &"OutputFiles.csv") 'This is to display if any files directly are present inside the \\server location and not under any project.
    call OutputFiles(objRootFolder.Files,ObjOutFile)
ObjOutFile.Close

Open in new window


Thanks
@Karrtik Iyer -  Sorry Karrtik Iyer I wanted to select both solutions and since I am new in Experts Exchange, by mistake I selected his. So I have Filed "A Request For Attention" as I didn't have Unaccept solution. Sorry once again and I will change once they give me access. Please have a look at the error handling request for recycle bin. Sorry Once again.

Thanks
That's ok vijayendra, but as per EE Policy I think, if two people have provided same solution (no difference in their approaches), the person who has provided the solution first should be given the points. If two people have provided different solutions and both are acceptable then both should get equal points. You can check with administrator if this is incorrect. Here everyone works hard to provide you the best solution. So please going forward keep that while accepting the answers. I shall check for the error for recycle bin. Also in my solution as you have already mentioned I have already covered to list the files directly in the root folder.
So I believe my solution is more complete.
Thanks,
Karrtik
In the main loop where getfiles is called, before calling get files check if there's any error..
If err.number = vbEmpty then
   Call GetFiles(project, ObjOutFile)
    Else WScript.echo "VBScript Error: " & err.number
End If
Thanks Karrtik Iyer - I have got your point and in future I will take care about it. I added the line of code given by you and the script is running but it is showing VBScript Error: 70 and blank files with only headers for all folders are formed.
Yes, I can adjust.  And add the logic to deal with protected files / folders.  Will work up those adjustments shortly...

~bp
Folder has a property called type, in the main loop check project.type, check it's value for recycle bin and then put a check to ignore it,
https://googleweblight.com/?lite_url=https://msdn.microsoft.com/en-us/library/y7k0wsxy(v%3Dvs.84).aspx&ei=mrs7ahw5&lc=en-IN&s=1&m=497&ts=1447159286&sig=APONPFmpdc7QqjGBlfkVFpK7EGPGDlHDNQ
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Both solutions equally meet my expectations.
Thanks to both of you
@Karrtik Iyer - Thanks for the reply, but one small request- I am not getting the list of files directly under the server. I know you have given the code for it here
set ObjOutFile = objFSO.CreateTextFile(objRootFolder.Name & "_" &"OutputFiles.csv") 'This is to display if any files directly are present inside the \\server location and not under any project.
    call OutputFiles(objRootFolder.Files,ObjOutFile)
ObjOutFile.Close

Open in new window

But if I give "D:\" drive I am not getting the output file - "D_OutputFiles.csv", I think it is to do with "\" in drive name. Please have a look at this. Once again thanks for wonderful comments & answers.

@Bill Prew - Thanks for your updated solution. But one small request as I have mentioned for Karrtik Iyer, But here I am getting the list of files directly under the drive but the filename is blank.  I think it is to do with "\" in drive name. Please have a look at this. Once again thanks for wonderful comments & answers.
Once again sorry to trouble you again, I found that some of the folders have very long names - they are saved from website, and I read that in windows there is a limit and names longer than 260 characters are not displayed. I used "dir d:\  /s /b > out.txt" and got the result. But is there any workaround or method which gives the result in vbscript as this folder or file is not in the list when your scripts are run.
Thanks
Hi Vijay,
Here is the updated script for the D drive problem.
I request/suggest you to please raise new question for new issues. As you test you might get more issues and for each of them continuing on the same question does not make much sense for us.

Thanks,
Karrtik
GetAllFiles.vbs
For the long file name and folder name issue, you can use DOS short name as alternative in VB script.
File or Folder has a property called shortpath.
Please check the link below:
http://www.codeproject.com/Tips/44521/Get-DOS-short-name-with-VbScript
set fso = CreateObject("Scripting.FileSystemObject") 
 
strLongName = Wscript.Arguments(0)
strShortName = "Invalid File/Folder - (" & strLongName & ")"
Set fsoFile = Nothing
 
On Error Resume Next
 
Set fsoFile = fso.GetFile(strLongName)
 
if Err.number <> 0 then
	Set fsoFile = fso.GetFolder(strLongName)
end if
 
if fsoFile is not nothing then
	strShortName = fsoFile.ShortPath
end if
Wscript.Echo strShortName

Open in new window

But this could possibly mean two long names might have same short name... I am not sure...
This should handle the drive root folder naming issue.

' Define base folder where project folders exist
strBaseDir = "\\server1\sharename1\basedir1"
strBaseDir = "C:\"

' Create filesystem object
Set objFSO = CreateObject("Scripting.FileSystemObject")

' Make sure base folder exists
If Not objFSO.FolderExists(strBaseDir) Then
    WScript.Echo("Starting folder does not exist : """ & strBaseDir & """.")
    Wscript.Quit
End If

' List any files in the base folder, but do not drill down into subfolders
Set objBaseDir = objFSO.GetFolder(strBaseDir)
ListFolder objBaseDir, False

' Process each folder in the base folder, and drill down into subfolders
For Each objFolder In objBaseDir.SubFolders
    ListFolder objFolder, True
Next

' Wrap up
WScript.Echo("Completed")


' Name the output file with this folders name and list all files under it
Sub ListFolder(objFolder, blnRecurse)
    ' Open a new file for this project folder with the folder name in the file name
    If objFolder.Name = "" Then
        strOutFile = Left(objFolder.Drive, 1) & ".txt"
    Else
        strOutFile = objFolder.Name & ".txt"
    End If
    Set objOutFile = objFSO.CreateTextFile(strOutFile)
    objOutFile.WriteLine("Type,File Name,File Path")

    ' Recursively get all files within this folder (and subfolders if wanted)
    GetFiles objFolder, objOutFile, blnRecurse

    ' Close this folders output file
    objOutFile.Close
    Set objOutFile = Nothing
End Sub


' Recursive function to list files in a folder, and the recurse into all child folders if wanted
Sub GetFiles(objFolder, objOutFile, blnRecurse)
    On Error Resume Next

    ' Log this folder name to output file
    objOutFile.WriteLine("Folder," & objFolder.Name & "," & objFolder.Path)

    ' Process all files, logging their info to output file
    For Each objFile In objFolder.Files
        objOutFile.WriteLine("File," & ObjFile.Name & "," & ObjFile.Path)
    Next

    ' Process all subfolders of this folder (recursion)
    If blnRecurse Then
       If Err.Number = 0 Then
           For Each objSubFolder In objFolder.SubFolders
               GetFiles objSubFolder, objOutFile, blnRecurse
           Next
       Else
           WScript.StdErr.WriteLine "*ERROR* [" & Err.Description & "] accessing folder [" & objFolder.Path & "]."
           Err.Clear
       End If
    End If

    On Error Goto 0
End Sub

Open in new window

~bp
Thanks Karrtik Iyer & Bill Prew for your responses. I will post other questions if I find difficult to solve myself. I basically work with excel, so I will post any difficulty I encounter in excel & vba. Once again, Thank you
Karrtik Iyer & Bill Prew - Sorry for again bothering you, but both of your code handles drive naming but foldername in server as "\\server1\sharename1\basedir1" is not handled.

@Karrtik Iyer - Your code gives the filename as "_Outputfiles.csv" and not "basedir1_Outputfiles.csv"

@Bill Prew - Your code gives filename as blank i.e no name.

Both lists the files under the server itself but unable to get filename.

@Karrtik Iyer - Your last comment is taken note and will start a new question from future but one last comment regarding this issue and I will close this question. Please bear with me on this particular as I don't want to add another question doing the same work.

Thanks both of you.
I just did a test here and my code worked fine, naming the file with the directory even when a network URI was used.  So in your example above I did indeed get a folder named "basedir1.txt".

~bp
Sorry Vijay for the delayed response, I was out on vacation.
I also like Bill tested my script using  example such as \\server1\sharename1\basedir1 as the server location and my output also generated correctly the output csv file for the root folder, which was basedir1_outputfilefiles.csv.
Please let us know if you are still facing any issues.
Thanks,
Karrtik