Vbscript - Compare and copy files from folder if newer than destination files - vbscript

I'm trying to design this script that's supposed to be used as a part of a logon script for alot of users. And this script is basically supposed to take a source folder and destination folder as basically just make sure that the destination folder has the exact same content as the source folder. But only copy if the datemodified stamp of the source file is newer than the destination file.
I have been thinking out this basic pseudo code, just trying to make sure this is valid and solid basically.
Dim strSourceFolder, strDestFolder
strSourceFolder = "C:\Users\User\SourceFolder\"
strDestFolder = "C:\Users\User\DestFolder\"
For each file in StrSourceFolder
ReplaceIfNewer (file, strDestFolder)
Next
Sub ReplaceIfNewer (SourceFile, DestFolder)
Dim DateModifiedSourceFile, DateModifiedDestFile
DateModifiedSourceFile = SourceFile.DateModified()
DateModifiedDestFile = DestFolder & "\" & SourceFile.DateModified()
If DateModifiedSourceFile < DateModifiedDestFile
Copy SourceFile to SourceFolder
End if
End Sub
Would this work? I'm not quite sure how it can be done, but I could probably spend all day figuring it out. But the people here are generally so amazingly smart that with your help it would take alot less time :)

Your algorithm looks good. Practically speaking, you would need to get the Files using a FileSystemObject, and retrieve their respective DateLastModified properties. You can do a DateDiff on the two dates to compare which is earlier.
Slightly modified examples from DevGuru:
Dim filesys,demofile, date1, date2
Set filesys = CreateObject("Scripting.FileSystemObject")
Set demofile = filesys.GetFile("filename1")
date1 = demofile.DateLastModified
demofile = filesys.GetFile("filename2")
date2 = demofile.DateLastModified
If DateDiff("d", date1, date2) > 0 Then
'date2 is more recent than date1, comparison by "day" ' ** Improvement **
End If
Edit: Misspelled the URL.
Improvement
In the comment, "date1" and "date2" have been exchanged.
The MSDN document says:
If date1 refers to a later time than date2, the DateDiff function returns a negative number.
http://msdn.microsoft.com/en-us/library/xhtyw595(v=vs.84).aspx

Your code looks reasonable. Just look out for readonly files and such.
You can use the FileSystemObject to do the actual file operations, just look at:
http://msdn.microsoft.com/en-us/library/6kxy1a51%28VS.85%29.aspx

Related

Iterate over pre-filtered list of folders

I'm working with a client's flat folder structure that has a single folder containing 45k subfolders with 8-digit folder names, e.g. 51023231. I have a small script that ripples through them and copies them into a bin-sorted set of subfolders elsewhere on the network (for use with SharePoint), such that the first 5 digits are used as a parent folder, i.e. the contents of 51023231 are copied into 51023\51023231. It works perfectly well, and I've managed to some modest optimisation when dealing with folders new to the destination.
However, it can take an hour or so to run over the entire 45k set of folders doing folder by folder comparisons, I was wondering if it was possible to run a system-level query to return only an initial list of folders whose modification dates were after a given point, and then run the existing script over that. I've done the usual Google-is-your-friend type trawl, and keep hitting the idea of using WMI to do this, but I don't get much further. Is this because it simply isn't possible with VBScript?
Any pointers gratefully received.
It's possible with VBScript using WMI. It's not something you'd be able to do using the FileSystemObject, if that's what you're implying.
You can query WMI's Win32_Directory class to filter folders by modified date. The only tricky part is the datetime format used by WMI. But the SWbemDateTime class can convert a VBScript date to a datetime value.
Here's an example:
' Create a datetime value for use in our WMI query...
Dim dt
Set dt = CreateObject("WbemScripting.SWbemDateTime")
dt.SetVarDate DateSerial(2015, 8, 31)
Dim objWMI
Set objWMI = GetObject("winmgmts:\\.\root\cimv2")
' Find all subfolders of 'c:\some\path' that were modified > 2015/08/31
Dim objFolders
Set objFolders = objWMI.ExecQuery("select * from Win32_Directory" _
& " where Drive='C:' and Path='\\some\\path\\' and LastModified>'" & dt & "'")
Dim objFolder
For Each objFolder in objFolders
WScript.Echo objFolder.Name
Next

Move files to folders based on first X characters of filename (vbs)

Hello my coding friends.
Sorry to ask this, but I thought it might be quicker to ask if someone has a script like this lying around.
I have about 2000+ files of audio mp3 files logged for a radio station I'm at, and I'd like to put them in to folders according to their recorded log date.
(Yes, I've now fixed the recording to do this correctly from now on, but this is in referent to what I've been doing with it: https://stephenmonro.wordpress.com/2015/05/22/setting-up-an-audio-logger/ )
The files I have are like this: (YYYYMMDD_HH00)
logs\20150424_0300.mp3
logs\20150424_0400.mp3
logs\20150424_0500.mp3
etc.
What I'd like is something like this:
\logs\8 digit date\filename with the same 8 digit date.mp3
Actual
\logs\20150424\20150424_0300.mp3
\logs\20150424\20150424_0400.mp3
\logs\20150424\20150424_0500.mp3
etc.
This is my pseudo code, I've made, but as I'm a little pressed for time and don't have hours to mess around guessing, I just wondered if anyone knew how to do it quickly.
A .VBS file is my prefered language.
Do
Read a filenames first 8 characters {left(8, filename)} (the date)
If not exist, create a folder called that first 8 characters
Move that file into the folder name
Loop (until all files are moved to the right locations)
Your pseudocode looks spot on to me. Assuming every file in your logs folder is consistently named, here's how it could be accomplished using the FileSystemObject library:
Const LOGS_FOLDER = "c:\logs"
Dim objFSO, objFile, strDate, strSub
Set objFSO = CreateObject("Scripting.FileSystemObject")
For Each objFile In objFSO.GetFolder(LOGS_FOLDER).Files
strDate = Left(objFile.Name, 8)
strSub = objFSO.BuildPath(LOGS_FOLDER, strDate)
' Create the folder if it doesn't already exist...
If Not objFSO.FolderExists(strSub) Then objFSO.CreateFolder strSub
' Move the file into its proper folder. Use "\" to indicate dest is folder...
objFile.Move strSub & "\"
Next

VB script will not traverse every file in a given folder

I am new to VBscript and am looking to write a simple script that changes a couple cells in a few thousand csv files in a given folder location. I have a good start, and it all seems to be working, except for the fact that when I run the script (from a .bat file that just calls the script) it only changes and moves 3-8 files at a time. The number of files it changes is random, its not like it always changes 5 files or something. I am not sure what is wrong in the code as to why it will not edit and move every single file and only does a couple at a time, here is what I have so far, thanks in advance for any help:
Set objFSO = Wscript.CreateObject("Scripting.FileSystemObject")
Set colFiles = ObjFSO.GetFolder("C:\Users\xxx\BadCSVs").Files
Set xl = CreateObject("Excel.Application")
For Each objFile in colFiles
If LCase(objFSO.GetExtensionName(objFile)) = "csv" Then
Set wb = xl.Workbooks.Open(objFile)
Set sht = xl.ActiveSheet
If(sht.Cells(1,11) <> "") Then
sht.Cells(1,8) = sht.Cells(1,8) & sht.Cells(1,9)
sht.Cells(1,9) = sht.Cells(1,10)
sht.Cells(1,10) = sht.Cells(1,11)
sht.Cells(1,11) = Null
wb.Save
wb.Close True
Else
'if file is opened up and has only 10 columns of data, then it makes no changes, then closes it.
wb.Close
End If
End If
Next
xl.Quit
Your EVIL global
On Error Resume Next
hides errors. Disable/Remove it and test again.
Your
wb.Close SaveChanges=True
passes the boolean result of comparing SaveChanges (undefined/empty) vs. the boolean literal True. Perhaps you copied VBA code
wb.Close SaveChanges:=True
(mark the colon) that is not legal in VBScript?
And
Set xl = CreateObject("Excel.Application")
should be paired with an
xl.Quit
If you invoke Excel in the loop, terminate it there. I would try to start/quit Excel out of the loop, but you should test that approach carefully.

needing help creating a script to find if a folder has been modified in the last day and if not create a txt file in a location

I'm trying to create a script that finds if a folder hasn't been modified in the last day and create a text file in a location. However if it has been modified in the last day I want it to quit the script.
At the moment, I have only been able to create one (due to my basic knowledge of VBscripting) that finds if a folder exists and if so creates a script.
This however, doesn't work as the subfolder is created daily with a new name and obviously this means my script would have to be changed daily which is pointless.
I need to have the parent folder read and a text file created in another locationif the last modified date isn't < 1 day.
This is the script so far:
Set objFSO = CreateObject("Scripting.FileSystemObject")
If objFSO.FolderExists("c:\test") Then
wsscript.quit
Else
dim filesys, filetxt, getname, path
Set filesys = CreateObject("Scripting.FileSystemObject")
Set filetxt = filesys.CreateTextFile("c:\test\test.txt", True)
path = filesys.GetAbsolutePathName("c:\test\test.txt")
getname = filesys.GetFileName(path)
filetxt.WriteLine("file doesnt exist.")
filetxt.Close
End If
I know I need to change the .folderExists line to something like
if file.DateLastModified > dateadd("h", -24, Now) then
I would like a day parameter rather than an hour; I know this means turning the h into a d but I am unsure past that.
it has been solved by Mr Bond! the wonderful man he is. however i now have another question, any idea how to add a command to send an outlook email into this? as the else option.
Use the DateLastModified property of the Folder object.
If objFSO.GetFolder("c:\test").DateLastModified >= Date - 1 Then
' Folder modified within last day
Else
' Folder modified more than a day ago
End
There's no need to use DateAdd() to add/subtract days. You can just use integer arithmetic.
Note that this will yield a time of zero/midnight. So it's really checking to see if the folder was modified since the start of the day yesterday, not in the last 24 hours. That may or may not be what you want.

Windows / NTFS: Number of files in a directory, without enumerating them

Is there a way in Windows to get the number of files in a directory (non-recursively is good enough) without the potentially significant overhead of enumerating them all through FindFirst/NextFile?
The purpose is for an estimate how many files need to be processed.
The directory structure is known and not deep, and folders usually don't contain unknown files.
Since the data is not essential to continue and the folder is virtually always on a local drive, an NTFS-specific command would be acceptable (provided that does not require elevation).
Any ideas?
Keeping track of the number of files in a directory is an overhead that doesn't provide any benefit for a file system, so none of them do it.
Counting files on a local drive should be fast enough for most purposes. It will certainly take a small fraction of the time needed to process the files.
Assuming that Indexing service is running and the directory is indexed, we can query the catalog and count the files on a given directory.
I dont know if querying the catalog is faster, its the only idea came on my mind.
Regards.
Sample code in VB.NET
Sub Main()
Try
' Catalog Name
Dim strCatalog As String = "System"
Dim strQuery As String
strQuery = "Select DocPageCount,DocTitle,Filename,Size,PATH,URL from SCOPE('shallow traversal of ""C:\Windows""')"
Dim connString As String = "Provider=MSIDXS.1;Integrated Security .='';Data Source='" & strCatalog & "'"
Dim cn As New System.Data.OleDb.OleDbConnection(connString)
cn.Open()
Dim cmd As New System.Data.OleDb.OleDbCommand(strQuery, cn)
Dim rdr As System.Data.OleDb.OleDbDataReader = cmd.ExecuteReader()
Dim files As Integer = 0
While rdr.Read()
files += 1
Console.WriteLine("Path: {0} Filename: {1} Size : {2}", rdr("PATH"), rdr("Filename"), rdr("Size"))
End While
rdr.Close()
rdr = Nothing
cmd.Dispose()
cmd = Nothing
cn.Close()
Console.WriteLine("Total Files: {0}", files)
Catch ex As Exception
Console.WriteLine(ex)
End Try
End Sub
More info: Searching your web site with the Microsoft Indexing Service and ASP.NET

Resources