Page 1 of 1 1
Topic Options
#196819 - 2009-11-24 03:05 AM Get most recent file name
Scottishfruit Offline
Fresh Scripter

Registered: 2006-09-20
Posts: 6
Loc: Sydney, Australia
Hi there

Does anyone know how I can enumerate a directory of files and then get the filename of the file with the most recent date and time?

I know how to enumerate the directory using DIR and Loop etc and I can use GETFILETIME to get the date and time of each file, but I would like to set a variable to the filename of the most recent file.

Thanks

Top
#196820 - 2009-11-24 09:53 AM Re: Get most recent file name [Re: Scottishfruit]
BoForce Offline
Fresh Scripter
**

Registered: 2005-10-22
Posts: 36
Loc: Leeuwarden, The Netherlands
Hello Scottishfruit,

Below you'll find an example of how to retrieve the filename of the most recent file with a directory.

 Code:
Dim $Array[0],$i,$Folder,$File,$MostRecent

$Folder = 'C:\'

For Each $File in DirPlus($Folder,'A-D')
   ReDim preserve $Array[$i]
   $Array[$i] = GetFileTime($File,) + '|' + $File
   $i = $i + 1
Next

$MostRecent = Split(CombSort($Array,1)[0],'|')[1]
? $MostRecent


$Folder is the folder from which you want to get the most recent file. Change it to your folder.
$MostRecent is variable that contains the most recent filename.

Please note that you require the UDF's DirPlus and CombSort, which can be found at http://www.kixtart.org/udf/

Top
#196821 - 2009-11-24 09:57 AM Re: Get most recent file name [Re: Scottishfruit]
Mart Moderator Offline
KiX Supporter
*****

Registered: 2002-03-27
Posts: 4672
Loc: The Netherlands
You could use the DirPlus() UDF to get all files and their last modification date and time and do some date math with the TimDiff() UDF on the outcome.

UDF Library » DirPlus() - a recursive dir tool
UDF Library » TimeDiff() - calculate time difference between 2 timestamps
KiXtart FAQ & How to's » How to use UDFs

 Code:
Break on

$files = dirplus("D:\", "/a-d")
For Each $file in $files
	? $file.DateLastModified
Next

Sleep 5

;DOT NOT MODIFY ANYTHING BELOW THIS LINE.
;BELOW IS A UDF AND THEY COME READY FOR USE AS THEY ARE.
;
;Function		DIRPlus()
;
;Author		Bryce Lindsay bryce@isorg.net
;
;Action		Returns an array containing directory files and folders
;
;Syntax		DIRPLUS("PATH","OPTIONS")
;
;Version		2.34
;
;Date Revised	2-10-05
;			2005.09.20 2.34 Filed the file/folder option "d" to be non language dependent, thanks Jochen
;
;Parameters	Path
;		  Full path To To a folder that you want To Return information on.
;		  "c:\program files"
;
;		  OPTIONS
;		  /S          Displays files In specified directory and all subdirectories.
;                             Use a /S# where # is equal to the subfolder depth that you want to recurse.
;
;		  /A          Displays files with specified attributes.
;		  attributes   D  Directories                R  Read-only files
;		               H  Hidden files               A  Files ready For archiving
;		               S  System files               -  Prefix meaning not
;
;		  /M          Apply mask string To filter based on InSTR(), separate Each search string witha a |
;
;		  /F          Return a given File extension like exe log or txt Seperate each extension type with a space
;
;
;Remarks	Finaly fixed this UDF For To handle multiple recursions,
;		also should have a faster responce time since it is using the FSO
;
;		***Please note that the syntax For version 2.0 of this UDF has changed.***
;
;		made some tweeks using feedback from Les! thanks!  Also NTDOC!
;
;Returns	Returns and array of FSO objects that are equal the file and folder objects of
;		the given path.  Also returns a @ERROR code For event handling.
;
;Dependencies 	FSO
;
;KiXtart Ver	4.22
;
;Example(s)	$Dir = dirplus("c:\program files") ;returns all files and folders In the "c:\program files" folder
;		$Dir = dirplus("c:\program files","/s") ;all fiels and folders including subfolders
;		$Dir = dirplus("c:\","/a-d") ;returns only a list of files In the c:\
;		$Dir = dirplus("c:\","/ad") ;returns only a list of folders In the c:\
;		$Dir = dirplus("c:\program files","/ad /s") ;returns only the folders including all subfolders.
;
;		$Dir = dirplus("g:\kix\udf","/s /ad /m dir") ; recursive subfolder search, folders only, using a mask string of "dir"
;
;		$desktop = dirplus("%userprofile%\desktop","/a-d")
;		For Each $file In $desktop
;			? $file
;			? $file.size
;		Next
;
Function DirPlus($path, optional $Options, optional $f, optional $sfflag)
	If Not VarType($f) Dim $f EndIf
	If Not VarType($sfflag) Dim $sfflag EndIf
	
	Dim $file, $i, $temp, $item, $ex1, $mask, $mask1, $maskArray, $maskarray1,
	$ex2, $code, $CodeWeight, $targetWeight, $weight, $masktrue
	Dim $tarray[0]
	
	$ex1 = SetOption(Explicit, on)
	$ex2 = SetOption(NoVarsInStrings, on)
	$codeWeight = 0
	
	If Not Exist($path) 
		$temp = SetOption(Explicit, $ex1)
		$temp = SetOption(NoVarsInStrings, $ex2)
		Exit @ERROR
	EndIf
	
	If Not VarType($f)
		$f = CreateObject("Scripting.FileSystemObject").getfolder($path)
	EndIf
	If @ERROR 
		$temp = SetOption(Explicit, $ex1)
		$temp = SetOption(NoVarsInStrings, $ex2)
		Exit @ERROR
	EndIf
	
	For Each $temp in Split($options, "/")
		$temp = Trim($temp)
		Select
			Case Left($temp, 1) = "s"
				If Not VarType($sfflag)
					If Val(Right($temp, -1)) = 0
						$sfflag = -1
					Else
						$sfflag = Val(Right($temp, -1))
					EndIf	
				EndIf
			Case Left($temp, 1) = "a"
				Select
					Case Right($temp, -1) = "d"
						$codeWeight = $codeWeight + 1
						$temp = "if $file.attributes & 16 " ;"if $file.type = 'File Folder' "
					Case Right($temp, -1) = "-d"
						$codeWeight = $codeWeight + 1
						$temp = "if ($file.attributes & 16)=0 " ;"if $file.type <> 'File Folder' "
					Case Right($temp, -1) = "s"
						$codeWeight = $codeWeight + 1
						$temp = "if $file.attributes & 4 "
					Case Right($temp, -1) = "-s"
						$codeWeight = $codeWeight + 1
						$temp = "if ($file.attributes & 4)=0 "
					Case Right($temp, -1) = "h"
						$codeWeight = $codeWeight + 1
						$temp = "if $file.attributes & 2 "
					Case Right($temp, -1) = "-h"
						$codeWeight = $codeWeight + 1
						$temp = "if ($file.attributes & 2)=0 "
					Case Right($temp, -1) = "r"
						$codeWeight = $codeWeight + 1
						$temp = "if $file.attributes & 1 "
					Case Right($temp, -1) = "-r"
						$codeWeight = $codeWeight + 1
						$temp = "if ($file.attributes & 1)=0 "
					Case Right($temp, -1) = "a"
						$codeWeight = $codeWeight + 1
						$temp = "if $file.attributes & 32 "
					Case Right($temp, -1) = "-a"
						$codeWeight = $codeWeight + 1
						$temp = "if ($file.attributes & 32)=0 "
				EndSelect
				$code = $temp + "$weight=$weight+1 endif" + @CRLF + $code
				
			Case Left($temp, 1) = "m"
				$maskarray = Split(Right($temp, -2), "|")
				$codeweight = $codeweight + 1
				$code = "$masktrue=0 for Each $mask in $maskarray if instr($file.name,$mask) $masktrue=1 " +
				"EndIf Next If $masktrue $weight=$weight+1 endif" + @CRLF + $code
			Case Left($temp, 1) = "f"
				$maskarray1 = Split(Right($temp, -2), " ")
				$codeweight = $codeweight + 1
				$code = "$masktrue=0 for Each $mask1 in $maskarray1 if substr($file.name,Instrrev($file.name,'.')+1)" +
				"=$mask1 $masktrue=1 EndIf Next If $masktrue $weight=$weight+1 endif" + @CRLF + $code
				
		EndSelect
	Next
	$code = "$weight = 0 $targetWeight = " + $codeweight + @CRLF + $code
	$code = $code + "if $weight = $targetweight Exit 1 endif"
	
	For Each $file in $f.subfolders
		If Execute($code)
			$tarray[$i] = $file
			$i = $i + 1
			ReDim preserve $tarray[$i]
		EndIf
		If $sfflag
			$temp = dirplus($file, $options, $file, $sfflag - 1)
			For Each $item in $temp
				$tarray[$i] = $item
				$i = $i + 1
				ReDim preserve $tarray[$i]
			Next
		EndIf
	Next
	For Each $file in $f.files
		If Execute($code)
			$tarray[$i] = $file
			$i = $i + 1
			
			ReDim preserve $tarray[$i]
		EndIf
	Next
	
	If $i
		ReDim preserve $tarray[$i - 1]
		$i = 0
	Else
		$tarray = 0
	EndIf
	
	$dirplus = $tarray
	$temp = SetOption(Explicit, $ex1)
	$temp = SetOption(NoVarsInStrings, $ex2)
	Exit @ERROR
EndFunction
_________________________
Mart

- Chuck Norris once sold ebay to ebay on ebay.

Top
#196822 - 2009-11-24 02:09 PM Re: Get most recent file name [Re: Mart]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4396
Loc: New Jersey
I have an application where I need to scan a few hundred-thousand files to determine if a file is newer than a specific timestamp. This is about 11 Gig of file data. Obviously, if I can find the newest file in the structure, I can tell if it's newer than the timestamp value.

I've tried many methods to enumerate the directory structure - Dir, DirList(), DirPlus, FSO, and more, but nothing is faster than a simple O/S DIR conmnmand, like this:
 Code:
$NewestFile = WshPipe('DIR ' + $FOLDER + /T:W /O-D | Find "/" | Sort /Rev')[0]
This runs in under a minute on my large structure, while other DirPlus/DirList type processes take 4-7 minutes. You will need to use the WshPipe UDF to make the call and return the data easily.

WshPipe returns an array, but we're restricting that to only the first element. /T:W requests the last written time to be displayed, /O-D sorts Newest First. Find "/" restricts the output to lines containing a date, which would only be lines describing files, not paths or other headers. The final Sort /Rev sorts in reverse order putting the newest file at the top, since the date & time come first in the line. From there, you can easily break that single line of data into DATE, TIME, SIZE, and NAME values.

It gets more complex if you need to search subfolders, but for a single folder, this is the fastest and easiest method. There are two UDFs in the library on my web site dealing with deterining if a folder structure has been modified - they might be useful, or at least provide some additional ideas.

Glenn
_________________________
Actually I am a Rocket Scientist! \:D

Top
#196826 - 2009-11-24 02:54 PM Re: Get most recent file name [Re: Glenn Barnas]
Richard H. Administrator Offline
Administrator
*****

Registered: 2000-01-24
Posts: 4946
Loc: Leatherhead, Surrey, UK
Most recent file in a single level directory? Low tech solution:
 Code:
Break ON
$=SetOption("Explicit","ON")

Dim $sDir,$sEntry,$sMRU

$sDir="D:\TEMP"
$sMRU="xxxxxxx"

$sEntry=Dir($sDir+"\*.*")
While Not @ERROR
	If Not (16 & GetFileAttr($sDir+"\"+$sEntry))
		If GetFileTime($sDir+"\"+$sEntry) > GetFileTime($sDir+"\"+$sMRU)
			$sMRU=$sEntry
		EndIf
	EndIf
	$sEntry=Dir()
Loop

"Most recently updated file: '"+$sMRU+"'"+@CRLF

Top
Page 1 of 1 1


Moderator:  Jochen, Allen, Radimus, Glenn Barnas, ShaneEP, Ruud van Velsen, Arend_, Mart 
Hop to:
Shout Box

Who's Online
1 registered (Allen) and 466 anonymous users online.
Newest Members
gespanntleuchten, DaveatAdvanced, Paulo_Alves, UsTaaa, xxJJxx
17864 Registered Users

Generated in 0.052 seconds in which 0.023 seconds were spent on a total of 13 queries. Zlib compression enabled.

Search the board with:
superb Board Search
or try with google:
Google
Web kixtart.org