kulisncc
asked on
VBS Script to Scan for Duplicate Files Using UNC Path
I got this script from the Hey Scripting Guy Blog and it works great but I need it to scan a system remotely rather than having the script ran locally using a UNC path. How can I get this script to use a UNC path rather than a local drive like it shows on line 4? Thanks.
Set objDictionary = CreateObject("Scripting.Dictionary")
Set objFSO = CreateObject("Scripting.FileSystemObject")
strStartFolder = "C:\Scripts"
Set objFolder = objFSO.GetFolder(strStartFolder)
Set colFiles = objFolder.Files
For Each objFile in colFiles
strName = objFile.Name
strPath = objFile.Path
If Not objDictionary.Exists(strName) Then
objDictionary.Add strName, strPath
Else
objDictionary.Item(strName) = objDictionary.Item(strName) & ";" & strPath
End If
Next
ShowSubfolders objFSO.GetFolder(strStartFolder)
For Each strKey in objDictionary.Keys
strFileName = strKey
If InStr(objDictionary.Item(strFileName), ";") Then
arrPaths = Split(objDictionary.Item(strFileName), ";")
Wscript.Echo strFileName
For Each strFilePath in arrPaths
Wscript.Echo strFilePath
Next
Wscript.Echo
End If
Next
Sub ShowSubFolders(Folder)
For Each Subfolder in Folder.SubFolders
Set objFolder = objFSO.GetFolder(Subfolder.Path)
Set colFiles = objFolder.Files
For Each objFile in colFiles
strName = objFile.Name
strPath = objFile.Path
If Not objDictionary.Exists(strName) Then
objDictionary.Add strName, strPath
Else
objDictionary.Item(strName) = objDictionary.Item(strName) & ";" & strPath
End If
Next
ShowSubFolders Subfolder
Next
End Sub
ASKER
I tried that but aparently the "Set objFSO = CreateObject("Scripting.Fi leSystemOb ject")" runs only on the loal system. I researched a bit and I read that I need to utilize WMI for what I need. Does that make any sense to you? Thanks
Hi Kulisncc,
Thats not entirely true. FileSystemObject is capable of using UNC paths (as prashant states above) to gain access to a remote machine but...
- the c$ share must be available
- you will need to run your vbscript file as either a domain admin, or as someone who will have admin rights on the remote computer, and the local computer you are running it from.
What exactly do you want to do with your script? I may have something already that you can use!
Thats not entirely true. FileSystemObject is capable of using UNC paths (as prashant states above) to gain access to a remote machine but...
- the c$ share must be available
- you will need to run your vbscript file as either a domain admin, or as someone who will have admin rights on the remote computer, and the local computer you are running it from.
What exactly do you want to do with your script? I may have something already that you can use!
ASKER
Thanks for your input Scottyworld. I want to script to run on a remote system and scan for duplicate files either on the entire system or a drive that I specify using a UNC path and then write a list of all the duplicate files to a csv. It would be great to have the script do the following:
1. scan the system for duplicate files
2. when it finds duplicate files have the script create a directory structure where the names of the directories are <computername>\<drive> and export its findings to a csv file where the name of the file is the date it was ran.
1. scan the system for duplicate files
2. when it finds duplicate files have the script create a directory structure where the names of the directories are <computername>\<drive> and export its findings to a csv file where the name of the file is the date it was ran.
ASKER
Actually, this is what I need help with:
1. Check to see if drives exist on remote system (D$, etc.)
2. If drives exists then scan each drive for duplicate files
3. Export the findings in the \\servername\\duplicate_fi les\D$\wha tever.csv
**I do not need the script to create the directory structure for me as in step 3 because I have taken care of this with a batch.
Thanks
1. Check to see if drives exist on remote system (D$, etc.)
2. If drives exists then scan each drive for duplicate files
3. Export the findings in the \\servername\\duplicate_fi
**I do not need the script to create the directory structure for me as in step 3 because I have taken care of this with a batch.
Thanks
Hi Kulisncc,
I have something that works well, except if it comes across a folder it doesn't have access to (for e.g: c:\system volume information) then it stops checking the current drive and moves to the next.
Am happy to post the code for you, or if you can wait a day I'll see if I can get the error checking working correctly
I have something that works well, except if it comes across a folder it doesn't have access to (for e.g: c:\system volume information) then it stops checking the current drive and moves to the next.
Am happy to post the code for you, or if you can wait a day I'll see if I can get the error checking working correctly
Try the following. I've got it to output to a txt file - you can easily import that into excel
Set objDictionary = CreateObject("Scripting.Dictionary")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set fs = CreateObject("Scripting.FileSystemObject")
Set a = fs.CreateTextFile("c:\temp\resultsfile.txt", True) 'this is your new output file
strComputer = "myPC1"
'Get a list of all the drives on the PC
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery ("Select * from Win32_LogicalDisk")
For Each objItem in colItems
If objItem.DriveType = 3 then 'ignore cd-rom and network drives
strStart = objItem.Name & "\" 'this will make the script start at the root of every drive, change if requierd e.g \temp
CheckForDuplicates(strStart)
On Error Resume Next 'if the strStart folder does not exist on the drive, script will skip to next physical drive
End If
Next
Function CheckForDuplicates(strStartFolder)
Set strName = nothing
Set strPath = nothing
a.WriteLine "Now checking drive " & strStartFolder
Set objFolder = objFSO.GetFolder(strStartFolder)
Set colFiles = objFolder.Files
For Each objFile in colFiles
strName = objFile.Name
strPath = objFile.Path
If Not objDictionary.Exists(strName) Then
objDictionary.Add strName, strPath
Else
objDictionary.Item(strName) = objDictionary.Item(strName) & ";" & strPath
End If
Next
ShowSubfolders objFSO.GetFolder(strStartFolder)
For Each strKey in objDictionary.Keys
strFileName = strKey
If InStr(objDictionary.Item(strFileName), ";") Then
arrPaths = Split(objDictionary.Item(strFileName), ";")
For Each strFilePath in arrPaths
If Left(strFilePath,1) = Left(strStartFolder,1) then
a.WriteLine strFilePath
End If
Next
End If
Next
End Function
Sub ShowSubFolders(Folder)
For Each Subfolder in Folder.SubFolders
On Error Resume Next 'if the folder is inaccessible, skip to next folder
Set objFolder = objFSO.GetFolder(Subfolder.Path)
Set colFiles = objFolder.Files
For Each objFile in colFiles
strName = objFile.Name
strPath = objFile.Path
If Not objDictionary.Exists(strName) Then
objDictionary.Add strName, strPath
Else
objDictionary.Item(strName) = objDictionary.Item(strName) & ";" & strPath
End If
Next
ShowSubFolders Subfolder
Next
End Sub
Very sorry, ignore the above code - that was from my test PC and will only work locally. Use this code for checking remote PCs...
Set objDictionary = CreateObject("Scripting.Dictionary")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set fs = CreateObject("Scripting.FileSystemObject")
Set a = fs.CreateTextFile("c:\temp\testfile.txt", True) 'this is your results output file
strComputer = "myPC1" 'name of the remote computer
'Get a list of all the drives on the PC
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery ("Select * from Win32_LogicalDisk")
For Each objItem in colItems
If objItem.DriveType = 3 then 'ignore cd-rom and network drives
strStart = "\\" & strComputer & "\" & Left(objItem.Name,1) & "$\" 'create the complete remote PC path then make the script start at the root of every drive, change if required e.g $\temp
CheckForDuplicates(strStart)
On Error Resume Next 'if the strStart folder does not exist on the drive, script will skip to next physical drive
End If
Next
Function CheckForDuplicates(strStartFolder)
Set strName = nothing
Set strPath = nothing
a.WriteLine "Now checking drive " & strStartFolder
Set objFolder = objFSO.GetFolder(strStartFolder)
Set colFiles = objFolder.Files
For Each objFile in colFiles
strName = objFile.Name
strPath = objFile.Path
If Not objDictionary.Exists(strName) Then
objDictionary.Add strName, strPath
Else
objDictionary.Item(strName) = objDictionary.Item(strName) & ";" & strPath
End If
Next
ShowSubfolders objFSO.GetFolder(strStartFolder)
For Each strKey in objDictionary.Keys
strFileName = strKey
If InStr(objDictionary.Item(strFileName), ";") Then
arrPaths = Split(objDictionary.Item(strFileName), ";")
For Each strFilePath in arrPaths
strCurrFolder = Left(strFilePath,(InStrRev(strFilePath,"$")-1))
strCurrDrive = Left(strStartFolder,(InStrRev(strStartFolder,"$")-1))
If StrComp(UCASE(strCurrFolder),UCASE(strCurrDrive)) = 0 then
a.WriteLine strFilePath
End If
Next
End If
Next
End Function
Sub ShowSubFolders(Folder)
For Each Subfolder in Folder.SubFolders
On Error Resume Next 'if the folder is inaccessible, skip to next folder
Set objFolder = objFSO.GetFolder(Subfolder.Path)
Set colFiles = objFolder.Files
For Each objFile in colFiles
strName = objFile.Name
strPath = objFile.Path
If Not objDictionary.Exists(strName) Then
objDictionary.Add strName, strPath
Else
objDictionary.Item(strName) = objDictionary.Item(strName) & ";" & strPath
End If
Next
ShowSubFolders Subfolder
Next
End Sub
ASKER
Awesome, I will definitely try this out. Thanks for your help Scottyworld.
ASKER
Hey bro, I run the script but the testfile.txt just reads: "Now checking drive \\computername\C$\"
and that's it. The testfile.txt does not increase in size, it just stays at 1KB.
and that's it. The testfile.txt does not increase in size, it just stays at 1KB.
ASKER
Here is code I got off the "Hey Scripting Guy Blog" from Microsoft's site. It scans a remote system for all directories and files, but I just want to change it to where it scans only for duplicate files. That's it. Can someone help me change this code to do what I need. Thanks everyone.
strComputer = "WN2790"
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
strFolderName = "C:\"
Set colSubfolders = objWMIService.ExecQuery _
("Associators of {Win32_Directory.Name='" & strFolderName & "'} " _
& "Where AssocClass = Win32_Subdirectory " _
& "ResultRole = PartComponent")
Wscript.Echo strFolderName
arrFolderPath = Split(strFolderName, "\")
strNewPath = ""
For i = 1 to Ubound(arrFolderPath)
strNewPath = strNewPath & "\\" & arrFolderPath(i)
Next
strPath = strNewPath & "\\"
Set colFiles = objWMIService.ExecQuery _
("Select * from CIM_DataFile where Path = '" & strPath & "'")
For Each objFile in colFiles
Wscript.Echo objFile.Name
Next
For Each objFolder in colSubfolders
GetSubFolders strFolderName
Next
Sub GetSubFolders(strFolderName)
Set colSubfolders2 = objWMIService.ExecQuery _
("Associators of {Win32_Directory.Name='" & strFolderName & "'} " _
& "Where AssocClass = Win32_Subdirectory " _
& "ResultRole = PartComponent")
For Each objFolder2 in colSubfolders2
strFolderName = objFolder2.Name
Wscript.Echo
Wscript.Echo objFolder2.Name
arrFolderPath = Split(strFolderName, "\")
strNewPath = ""
For i = 1 to Ubound(arrFolderPath)
strNewPath = strNewPath & "\\" & arrFolderPath(i)
Next
strPath = strNewPath & "\\"
Set colFiles = objWMIService.ExecQuery _
("Select * from CIM_DataFile where Path = '" & strPath & "'")
For Each objFile in colFiles
Wscript.Echo objFile.Name
Next
GetSubFolders strFolderName
Next
End Sub
Hi,
Can you try running it locally on a PC - just put the local PC name in te script instead of a remote one.
The text file results would appear like that if you didn't have permissions on the remote PC.
You need to be runing the script while logged on as either a domain admin, or an account that has admin rights on the remote PC.
At line 76 if may be worth throwing in the following so you know when it finishes. Mine took ages to run on the whole of a 500gb C drive. Try setting up some test folders and duplicate files and change line 15 to $\temp just to limit down the search criteria to make it quicker
76: wscript.echo "Finished"
Can you try running it locally on a PC - just put the local PC name in te script instead of a remote one.
The text file results would appear like that if you didn't have permissions on the remote PC.
You need to be runing the script while logged on as either a domain admin, or an account that has admin rights on the remote PC.
At line 76 if may be worth throwing in the following so you know when it finishes. Mine took ages to run on the whole of a 500gb C drive. Try setting up some test folders and duplicate files and change line 15 to $\temp just to limit down the search criteria to make it quicker
76: wscript.echo "Finished"
ASKER
Okay, I will give it another shot.
ASKER
DUDE!! It does work - AWESOME!! Is there anyway to have it space between each of its findings and have the name of the duplicate files it finds as the header before the list of the locations? For instance:
somefile1.txt
c:\somefile.txt
c:\windows\somefile.txt
somefile2.txt
c:\somefile2.txt
c:\windows\somefile2.txt
Thanks again bro.
somefile1.txt
c:\somefile.txt
c:\windows\somefile.txt
somefile2.txt
c:\somefile2.txt
c:\windows\somefile2.txt
Thanks again bro.
:) glad I could help. Will get back to you with the modifications in a while, but its just a case of putting a couple of a.writeLine lines in to put in the blank lines if you wanted to try in the meantime
Slightly more complicated than I thought as you need to keep track of the last filename checked and the current one. Try the attached script. If you don't want the "Now checking drive" lines, just comment them out.(lines 24-26)
Set objDictionary = CreateObject("Scripting.Dictionary")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set fs = CreateObject("Scripting.FileSystemObject")
Set a = fs.CreateTextFile("c:\temp\testfile.txt", True) 'this is your results output file
strComputer = "myPC1" 'name of the remote computer
'Get a list of all the drives on the PC
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery ("Select * from Win32_LogicalDisk")
For Each objItem in colItems
If objItem.DriveType = 3 then 'ignore cd-rom and network drives
strStart = "\\" & strComputer & "\" & Left(objItem.Name,1) & "$\" 'create the complete remote PC path then make the script start at the root of every drive, change if required e.g $\temp
CheckForDuplicates(strStart)
On Error Resume Next 'if the strStart folder does not exist on the drive, script will skip to next physical drive
End If
Next
Function CheckForDuplicates(strStartFolder)
Set strName = nothing
Set strPath = nothing
a.WriteLine
a.WriteLine
a.WriteLine "Now checking drive " & strStartFolder
Set objFolder = objFSO.GetFolder(strStartFolder)
Set colFiles = objFolder.Files
For Each objFile in colFiles
strName = objFile.Name
strPath = objFile.Path
If Not objDictionary.Exists(strName) Then
objDictionary.Add strName, strPath
Else
objDictionary.Item(strName) = objDictionary.Item(strName) & ";" & strPath
End If
Next
ShowSubfolders objFSO.GetFolder(strStartFolder)
For Each strKey in objDictionary.Keys
strFileName = strKey
If InStr(objDictionary.Item(strFileName), ";") Then
arrPaths = Split(objDictionary.Item(strFileName), ";")
For Each strFilePath in arrPaths
strCurrFolder = Left(strFilePath,(InStrRev(strFilePath,"$")-1))
strCurrDrive = Left(strStartFolder,(InStrRev(strStartFolder,"$")-1))
strCurrFileName = Right(strFilePath,(Len(strFilePath) - InStrRev(strFilePath,"\")))
If StrComp(UCASE(strCurrFolder),UCASE(strCurrDrive)) = 0 then
If strLastFileName = strCurrFileName then
a.WriteLine strFilePath
Else
a.WriteLine
a.WriteLine
a.WriteLine strCurrFileName
a.WriteLine
a.WriteLine strFilePath
strLastFileName = strCurrFileName
End If
End If
Next
End If
Next
End Function
Sub ShowSubFolders(Folder)
For Each Subfolder in Folder.SubFolders
On Error Resume Next 'if the folder is inaccessible, skip to next folder
Set objFolder = objFSO.GetFolder(Subfolder.Path)
Set colFiles = objFolder.Files
For Each objFile in colFiles
strName = objFile.Name
strPath = objFile.Path
If Not objDictionary.Exists(strName) Then
objDictionary.Add strName, strPath
Else
objDictionary.Item(strName) = objDictionary.Item(strName) & ";" & strPath
End If
Next
ShowSubFolders Subfolder
Next
End Sub
ASKER
Okay, I will try this out. Thanks brotha for your help
ASKER
I swear I will leave you alone after this one last thing. How can I use a UNC path rather than a local drive to save the .txt to as in the following line:
Set a = fs.CreateTextFile("c:\temp \testfile. txt", True) 'this is your results output file
I would like to save it to something like: \\myserver\share\test.txt
Thanks alot Scottyworld
I told you I suck at VBS
Set a = fs.CreateTextFile("c:\temp
I would like to save it to something like: \\myserver\share\test.txt
Thanks alot Scottyworld
I told you I suck at VBS
There should be no reason against just putting that path into that line of code. UNC paths should work fine, as long as the user account running the script has write access to that location.
Set a = fs.CreateTextFile("\\myser ver\share\ test.txt", True) 'this is your results output file
Set a = fs.CreateTextFile("\\myser
ASKER
Scottyworld, it worked - Sorta. I swear if you can help me out with this one last issue, I will cease any further inquiries. Here is my issue:
There are multiple drives on the system I need to scan for duplicate files, but the script that you put together seems to only scan the C: (from what I can tell from the csv file I have it exporting to) and is there any way I can get the script to prompt for a computer name to scan instead of having to edit the .vbs file itself, and to also create a folder in the UNC path I specify, then name the folder as the computer name of the system it is scanning? The problems that I seem to have with VB scripting is that I know some of the code, but I am not too skilled at piecing them together. I am very good at batch scripting but this of course is an older scripting technology and along with even VBS are becoming obsolete in the Windows world due to the advent of Powershell. So anyway, I don't understand why it is not scanning the other drives, but creating folders named after the computer names of the systems being scanned, I am presuming I would use the following code:
There are multiple drives on the system I need to scan for duplicate files, but the script that you put together seems to only scan the C: (from what I can tell from the csv file I have it exporting to) and is there any way I can get the script to prompt for a computer name to scan instead of having to edit the .vbs file itself, and to also create a folder in the UNC path I specify, then name the folder as the computer name of the system it is scanning? The problems that I seem to have with VB scripting is that I know some of the code, but I am not too skilled at piecing them together. I am very good at batch scripting but this of course is an older scripting technology and along with even VBS are becoming obsolete in the Windows world due to the advent of Powershell. So anyway, I don't understand why it is not scanning the other drives, but creating folders named after the computer names of the systems being scanned, I am presuming I would use the following code:
Would I use this code to type the computer name in an input box?
-------------------------------------------------------------------
strComputer = inputbox("Type a computer name","Enter computer name")
if strComputer = "" then strComputer = "."
-------------------------------------------------------------------
Then would I use this code to create a folder and then name it the computer name?
-------------------------------------------------------------------
if Not fso.FolderExists("strComputer") then
fso.CreateFolder "strComputer"
End If
-------------------------------------------------------------------
Plus, I am assuming I would set the above code prior to the following line of course:
-------------------------------------------------------------------
Set a =
fs.CreateTextFile
("\\strComputer\strComputer_folder\find_duplicate_files.csv", True) 'this is your results output file
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I just ran it but again it seems to only pull from the C: - other than that, it works perfectly. I then commented out lines 29 and 33 as you suggested and it didnt run.
very odd!
can you just run the following code on your PC and see what drives it comes back with
This will lst all drives, their type, and their description. Just note down the type and description for the drive letters you want to check. I'm wondering if they are not being seen as a drivetype of 3 for some reason. This will run on a remote PC too - just change the PC number
can you just run the following code on your PC and see what drives it comes back with
This will lst all drives, their type, and their description. Just note down the type and description for the drive letters you want to check. I'm wondering if they are not being seen as a drivetype of 3 for some reason. This will run on a remote PC too - just change the PC number
strComputer ="."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery ("Select * from Win32_LogicalDisk")
For Each objItem in colItems
wscript.echo objItem.Name & ", " & objItem.DriveType & ", " & objItem.Description
Next
ASKER
It shows that all the drives are in fact drive type 3 - I think will try running it locally and see what happens
ASKER
I forgot to mention that there are two HDD's in this system. One is the C: which this script has no problem seeing but the other HDD has multiple partitions (4 to be exact). Could this be why it is not picking up the other drives?
As long as the mini script I gave you above lists all of the drives you want to check, then the full script should check them all also.
Did you try running it locally to see if it made a difference?
Have just run the script from my local PC to a remote server(which has several hard drives in it) and it has run across all of them
Did you try running it locally to see if it made a difference?
Have just run the script from my local PC to a remote server(which has several hard drives in it) and it has run across all of them
ASKER
Well damn, I don't get it then. Maybe if I walk over to the data center, find the server I need to scan and kick the hell out of it, that will work - LOL. The output to the csv file only shows that the C$ was scanned. I will keep playing with it. I should have admin privileges on the system I need to scan. I will double check my permissions again.
Thanks for the points - I honestly can't think of what may be causing it to stop on the C drive. Even if it can't access any files on the other drives it should still put a log in the txt file saying "now checking drive xx" (assuming you've left line 41 in)
Admin rights shouldn't be the problem, as you can access one physical drive, so the rest should be fine also.
You could try commenting out the "on error resume next" lines (maybe one at a time) to see if you can pinpoint where it is stopping - be warned though, doing this will make the script fail when it encounters a folder it cannot access (like the 'System Volume Information' on Win XP)
Admin rights shouldn't be the problem, as you can access one physical drive, so the rest should be fine also.
You could try commenting out the "on error resume next" lines (maybe one at a time) to see if you can pinpoint where it is stopping - be warned though, doing this will make the script fail when it encounters a folder it cannot access (like the 'System Volume Information' on Win XP)
strStartFolder = "\\servername\C$\Scripts"