Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Moving Files Based on Modified Data Recursively

Status
Not open for further replies.
Jun 8, 2011
30
CA
Hello,

I have a need and scripting challenge for the forum members.

I work for a large engineering firm and we have very large data stores that need to be archived occasionally. I need a script that can start at a top level folder and then recursively move down the folder structure that looks at all the files in each child folder and determines the file with the most recent modified date. Based on the most recent modified date, I would like to move that child folder to an archive folder if the most recent modification occurred over 6 months ago.

If anyone can help I'd sure appreciate it!
 
Just to clarify,

A) find the most recently modified file and archive its parent folder if the file was modified over 6 months ago?

B) archive all file folders that contain files that were modified over 6 months ago

A or B?

-Geates

"I hope I can feel and see the change - stop the bleed inside a feel again. Cut the chain of lies you've been feeding my veins; I've got nothing to say to you!"
-Infected Mushroom

"I do not offer answers, only considerations."
- Geates's Disclaimer
 
Thank you for the reply Geates.

If the most recent file in a subfolder was modified over 6 months ago, that would mean the project is probably closed and I'd like to move the entire subfolder to the archive folder. Another part of the challenge is that most subfolders have their own subfolders and I need to check everything in the subfolders.

Folder1
Subfolder1
Subfolder1
Subfolder1
Folder 2
Subfolder1
Subfolder1
Subfolder2

I need to look into Folder 1 and then all of its subfolders to see if anything was modified within 6 months, if not, archive Folder1.

Then look in Folder2 and its subfolders and their subfolders to see if anything was modified within 6 months, if not, archive Folder2.

If there is one file in any subfolder modified more recently than 6 months, I dont want to touch the parent subfolder.

Hopefully that makes sense.

Thanks!
 
Can't really test as I don't have an environment that meets your criteria.

A)

Code:
set objFSO = CreateObject("Scripting.FileSystemObject")
set objShell = CreateObject("WScript.Shell")

function findRecentFile(strDir, strRecent)
	set objFolder = objFSO.GetFolder(strDir)
	for each objSubFolder in objFolder.SubFolders
		strRecent = findRecentFile(objSubFolder.Path, strRecent)
	next
	
	for each objFile in objFolder.Files
		if (strRecent = "") then 
			strRecent = objFile.Path
		else
			if (objFile.DateLastModified > objFSO.GetFile(strRecent).DateLastModified) then strRecent = objFile.Path
		end if
	next
	findRecentFile = strRecent
end function

intAge = 6 'months
strSource = "C:\temp"
strDestination = "C:\archives"

strFile = findRecentFile(strSource, "")
strModDate = objFSO.GetFile(strFile).DateLastModified

if (datediff("m", strModDate, now) > intAge) then
	objFSO.MoveFolder objFSO.GetParentFolder(strFile), strDestination, true
end if

Option B can be accomplished by running 'A' indefinitely :)

-Geates

"I hope I can feel and see the change - stop the bleed inside a feel again. Cut the chain of lies you've been feeding my veins; I've got nothing to say to you!"
-Infected Mushroom

"I do not offer answers, only considerations."
- Geates's Disclaimer
 
Thanks Geates. I ran your script but nothing happened. I changed the two paths to reflect my test environment. I've robocopied a test file structure with time stamps so I do have files that havent been modified in over 6 months.

----------------------------

set objFSO = CreateObject("Scripting.FileSystemObject")
set objShell = CreateObject("WScript.Shell")

function findRecentFile(strDir, strRecent)
set objFolder = objFSO.GetFolder(strDir)
for each objSubFolder in objFolder.SubFolders
strRecent = findRecentFile(objSubFolder.Path, strRecent)
next

for each objFile in objFolder.Files
if (strRecent = "") then
strRecent = objFile.Path
else
if (objFile.DateLastModified > objFSO.GetFile(strRecent).DateLastModified) then strRecent = objFile.Path
end if
next
findRecentFile = strRecent
end function

intAge = 6 'months
strSource = "C:\Users\BWeisz\Desktop\Move\Live"
strDestination = "C:\Users\BWeisz\Desktop\Move\Archive\"

strFile = findRecentFile(strSource, "")
strModDate = objFSO.GetFile(strFile).DateLastModified

if (datediff("m", strModDate, now) > intAge) then
objFSO.MoveFolder objFSO.GetParentFolder(strFile), strDestination, true
end if
 
Actually, you'll want to iterate through parent folders only, checking to see if ANY child file was recently modified. If not, move them. Change the last three lines

Code:
if (datediff("m", strModDate, now) > intAge) then
    objFSO.MoveFolder objFSO.GetParentFolder(strFile), strDestination, true
end if

to..

Code:
[green]'iterate the strSource folder[/green]
for each objFolder in objFSO.GetFolder(strSource).SubFolders
    [green]'For each folder, it will recursively find the most recent file in the child folders.[/green]
	strFile = findRecentFile(strSource, "")
	strModDate = objFSO.GetFile(strFile).DateLastModified

    [green]'If that file is older than 6 months[/green]	
    if (datediff("m", strModDate, now) > intAge) then
        [green]'move it[/green]
		objFolder.Move strDestination, true
	end if
next

-Geates

"I hope I can feel and see the change - stop the bleed inside a feel again. Cut the chain of lies you've been feeding my veins; I've got nothing to say to you!"
-Infected Mushroom

"I do not offer answers, only considerations."
- Geates's Disclaimer
 
Geates, I made your change but still no movement.

I've attached a screenshot of my live directory.

---------

set objFSO = CreateObject("Scripting.FileSystemObject")
set objShell = CreateObject("WScript.Shell")

function findRecentFile(strDir, strRecent)
set objFolder = objFSO.GetFolder(strDir)
for each objSubFolder in objFolder.SubFolders
strRecent = findRecentFile(objSubFolder.Path, strRecent)
next

for each objFile in objFolder.Files
if (strRecent = "") then
strRecent = objFile.Path
else
if (objFile.DateLastModified > objFSO.GetFile(strRecent).DateLastModified) then strRecent = objFile.Path
end if
next
findRecentFile = strRecent
end function

intAge = 6 'months
strSource = "C:\Users\BWeisz\Desktop\Move\Live"
strDestination = "C:\Users\BWeisz\Desktop\Move\Archive\"

strFile = findRecentFile(strSource, "")
strModDate = objFSO.GetFile(strFile).DateLastModified

'iterate the strSource folder
for each objFolder in objFSO.GetFolder(strSource).SubFolders
'For each folder, it will recursively find the most recent file in the child folders.
strFile = findRecentFile(strSource, "")
strModDate = objFSO.GetFile(strFile).DateLastModified
'If that file is older than 6 months
if (datediff("m", strModDate, now) > intAge) then
'move it
objFolder.Move strDestination, true
end if
next
 
 http://www.dowlhkm.com/brett.jpg
Oops. 2 errors. 1 major

1. strFile = findRecentFile([red]objFolder.Path[/red], "")
2. objFolder.Move strDestination [red]& objFolder.Name[/red]

Try...

Code:
for each objFolder in objFSO.GetFolder(strSource).SubFolders
    strFile = findRecentFile(objFolder.Path, "")
    strModDate = objFSO.GetFile(strFile).DateLastModified
    if (datediff("m", strModDate, now) > intAge) then
        objFolder.Move strDestination & objFolder.Name
    end if
next

-Geates

"I hope I can feel and see the change - stop the bleed inside a feel again. Cut the chain of lies you've been feeding my veins; I've got nothing to say to you!"
-Infected Mushroom

"I do not offer answers, only considerations."
- Geates's Disclaimer
 
Thanks Geates. You're making some progress. I see that it is now moving folders, but it is moving the subfolders instead of the subfolder's parent folder.

I am also receiving an error in line 32, char 9.

"File already exists
 
Ha! That's because objFolder is being changed within the findRecentFile function and then being reference outside the function, thus moving the child folder (instead of the parent) and causing a error when moving a sibling folder (cannot move a folder to a destination that already exists.)

objFolder needs to be DIMed within the function so it is only accessible within the function (local to the function)

Simply add "dim objFolder" as the first line of the function

Code:
function findRecentFile(strDir, strRecent)
	[red]dim objFolder[/red]
	set objFolder = objFSO.GetFolder(strDir)
...

-Geates

"I hope I can feel and see the change - stop the bleed inside a feel again. Cut the chain of lies you've been feeding my veins; I've got nothing to say to you!"
-Infected Mushroom

"I do not offer answers, only considerations."
- Geates's Disclaimer
 
Thanks Geates. It started to work as it moved 11 folders but then erorred out. Also, it moved some folders that it should not have. Which is probably related to the error.

I am receiving an error in line 31, char 5.

Invalide procedure call or argument.

-------------

set objFSO = CreateObject("Scripting.FileSystemObject")
set objShell = CreateObject("WScript.Shell")

function findRecentFile(strDir, strRecent)
dim objFolder
set objFolder = objFSO.GetFolder(strDir)
for each objSubFolder in objFolder.SubFolders
strRecent = findRecentFile(objSubFolder.Path, strRecent)
next

for each objFile in objFolder.Files
if (strRecent = "") then
strRecent = objFile.Path
else
if (objFile.DateLastModified > objFSO.GetFile(strRecent).DateLastModified) then strRecent = objFile.Path
end if
next
findRecentFile = strRecent
end function

intAge = 6 'months
strSource = "C:\Users\BWeisz\Desktop\Move\Live"
strDestination = "C:\Users\BWeisz\Desktop\Move\Archive\"

strFile = findRecentFile(strSource, "")
strModDate = objFSO.GetFile(strFile).DateLastModified

'iterate the strSource folder
for each objFolder in objFSO.GetFolder(strSource).SubFolders
strFile = findRecentFile(objFolder.Path, "")
strModDate = objFSO.GetFile(strFile).DateLastModified
if (datediff("m", strModDate, now) > intAge) then
objFolder.Move strDestination & objFolder.Name
end if
next
 
Geates, scratch what I said about moving the wrong folders. They are indeed correct, but there were 2 it should have moved but didnt.
 
line 31:
Code:
strModDate = objFSO.GetFile(strFile).DateLastModified

Most likely because the folder contains no files, thus strFile is nothing, this command will error out. Wrap it in an if..then statement to prevent this. Also, no need for the strFile and strModDate before the for..each.

Code:
[s]strFile = findRecentFile(strSource, "")
strModDate = objFSO.GetFile(strFile).DateLastModified[/s]

for each objFolder in objFSO.GetFolder(strSource).SubFolders
	strFile = findRecentFile(objFolder.Path, "")
	[green]if (strFile <> "") then[/green]
		strModDate = objFSO.GetFile(strFile).DateLastModified
		if (datediff("m", strModDate, now) > intAge) then
			objFolder.Move strDestination & objFolder.Name
		end if
	[green]end if[/green]
next


-Geates

note: no need to keep posting the code

"I hope I can feel and see the change - stop the bleed inside a feel again. Cut the chain of lies you've been feeding my veins; I've got nothing to say to you!"
-Infected Mushroom

"I do not offer answers, only considerations."
- Geates's Disclaimer
 
Thank you Geates. I made the modification and it ran without error. It did leave one blank folder that hasnt been modified for 6+ months and one other folder that did have information in it.

Any idea why it would leave those?
 
It didn't move the blank folder because moving a folder is contingent on FILE modification dates, not folders. The folder with information in it must have a file the was recently modified, otherwise, it would have been moved.

If there is no file (strFile = "") then check the date of the folder

Code:
for each objFolder in objFSO.GetFolder(strSource).SubFolders
    strFile = findRecentFile(objFolder.Path, "")
    if (strFile <> "") then
        strModDate = objFSO.GetFile(strFile).DateLastModified
    [green]else
        strModDate = objFolder.DateLastModified
    end if[/green]
    if (datediff("m", strModDate, now) > intAge) then
        objFolder.Move strDestination & objFolder.Name
    end if

next

-Geates

"I hope I can feel and see the change - stop the bleed inside a feel again. Cut the chain of lies you've been feeding my veins; I've got nothing to say to you!"
-Infected Mushroom

"I do not offer answers, only considerations."
- Geates's Disclaimer
 
Also, because a difference in month can have a margin of error of 30 days (1/1/2011 vs. 6/30/2011, the difference is 5 months but 183 days - which is greater than 5 months), you may want your criteria to be based on days.

Code:
intAge = 180 '30 days * 6 months
if (datediff([b][green]"d"[/green][/b], strModDate, now) > intAge) then

-Geates

"I hope I can feel and see the change - stop the bleed inside a feel again. Cut the chain of lies you've been feeding my veins; I've got nothing to say to you!"
-Infected Mushroom

"I do not offer answers, only considerations."
- Geates's Disclaimer
 
Thank you. And I did find the file that caused the other folder not to move.
 
I wrote this script , it uses 7-zip after finding the files older that a given time - dunno if its any good to you:


Dim WSshell

Set fso = CreateObject("Scripting.FileSystemObject")
Set objShell = wscript.createObject("wscript.shell")

'Install path of 7 Zip, ignor if using Environment variables
InstallPath = "c:\Program Files\7-Zip"

'Target Folder created on fly (and deleted, after zip (strDirectory) is created
myTargetFolder = "c:\store\" & replace(date,"/","_")

'Zip archive location ( Need to create c:\Archive manually )
'Can be a network drive
strDirectory = "c:\Archived_LogFiles\" & "DIONE_IIS_Logs_" & replace(date,"/","_")

'Folder to search through
mySourceFolder="C:\logs"

'wscript.echo strdirectory



'set demofolder = fso.GetFolder (strdirectory)

Set WSHShell = WScript.CreateObject("WScript.Shell")



set root=fso.getFolder(mySourceFolder)

call folderlist(root)

sub folderlist(grp)

call filelist(grp)

for each fldr in grp.subFolders

set nf=fso.GetFolder(fldr.path)

call folderlist(nf)

set nf=nothing

next

end sub


sub filelist(grp)




subfldr=myTargetFolder & mid(grp,len(mySourceFolder)+1)

if fso.folderExists(subfldr)=false then fso.CreateFolder(subfldr)

for each file in grp.files

if fileTest(file) = true then


file.move subfldr & "\"

end if

next

end sub

function fileTest(item)

fileTest=False

modDate=item.DateLastModified


If DateDiff("d", item.DateLastModified, Now) >0 Then

fileTest=True
end if

end function

call Sevenzip

sub Sevenzip

on error resume next

strCommand = "7za a -tzip -v100m " & strDirectory & " " & myTargetFolder
wscript.echo strCommand
objShell.CurrentDirectory = InstallPath

strRun = objShell.Run(strCommand, 0, True)

If Err <> 0 Then
wscript.echo Err.Number & ", " & Err.Description
set oTSOut = fso.openTextFile("c:\errors.txt", 8)
oTSOut.writeline date & " " & time & " Error Num- " & Err.Number & ", " & " Error Description " & " " & Err.Description
wscript.quit
Else
On Error Goto 0



call deleteFolder(MyTargetFolder)
end if
end sub



sub DeleteFolder(MyTargetFolder)

fso.DeleteFolder(MyTargetFolder)
set oTSOut = fso.openTextFile("c:\errors.txt", 8)
oTSOut.writeline date & " " & MyTargetFolder & " Has been Deleted"
oTSOut.writeline "=============================================================="
End sub
 
Geates,

Sorry to bother you again but I found a gotcha when I moved the script to the production environment.

In our production environment we have a parent folder and then subfolders below. The subfolders contain the projects so the script needs to check the folders in each subfolder and return that project subfolders name. Currently the script returns the first level subfolder when anything below is out of date, but I need to know which subfolder of the subfolder is out of date. Hopefully that makes sense. The file structure is below. If you could help me modify this script I'd sure appreciate it.

Thanks!


This is what the folder structure looks like:

MasterFolder
00
Project1
Project2
Project3
01
Project1
02
Project1
Project2
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top