7

In VBScript, I want to get a list of files in a folder ordered by creation date. I saw that in order to do that I will need to either use a record set (seems like an overkill to me) or sort the collection myself (I think I can avoid it and I want my code to be shorter).

Since I am the one creating the files, I create them with names that begin with the date (yyyy_mm_dd) so I though that if I can get the files at least ordered by name then I'm all set. Unfortunately, the MSDN documentation of the Files collection from FileSystemObject doesn't say anything about the order of the collection. Does anyone know of some other secret documentation or something like that that can be more specific?

shwartz
  • 631
  • 3
  • 13
  • 29

3 Answers3

12

Is it really too much code to sort?

set fso = CreateObject("Scripting.FileSystemObject")

Set outputLines = CreateObject("System.Collections.ArrayList")
for each f in fso.GetFolder(".").files
  outputLines.Add f.Name
next
outputLines.Sort() ' 5 lines...

For Each outputLine in outputLines
  set file = fso.GetFolder(".").files.item (outputLine&"")
  Wscript.Echo file.name ' TODO: your thing here
Next
Papasmile
  • 624
  • 1
  • 4
  • 22
  • Thanks. It is short but since it is using a .net object the script may have problems in the future when there are .net upgrades (though it is unlikely with such a basic class as the ArrayList). I want to have this script scheduled to run once a day and probably no one is going to be there to handle problems - so I want to minimize the risk. – shwartz Jun 05 '13 at 09:06
  • 1
    The question is about file object by date and this sorts a collections of names, by name. – HackSlash Aug 03 '22 at 00:25
  • And ArrayList requires .Net 3.5 which is no longer installed by default. – LesFerch Sep 06 '22 at 15:30
9

If you want to get the files in a folder in a specific order, you'll have to do it yourself. If you don't like the ADO recordset or using a sortable .NET collection, you can shell out (.Run, .Exec) and process the output of dir /A:-D /B /O:D /T:C (no folders, bare format (no header/summary), order:date, timefield:creation).

Update:

While I surely can show examples where the .Files collection delivered its elements ordered by name, Mr. Gates explicitly says:

INFO: Limitations of the FileSystemObject ... Cannot sort file names from the files collection - you can iterate through the File objects in the Files collection to obtain a list of the files in a folder. However, the File objects are not sorted. You need to use a sort routine to sort the File objects in the Files collection.

Minimalistic demo code that shows: You need a shell (%comspec%) if you want to use shell features - like intrinsic commands:

Option Explicit

Dim goFS  : Set goFS = CreateObject("Scripting.FileSystemObject")
Dim goWS  : Set goWS = CreateObject("WScript.Shell")
Dim csDir : csDir = "c:\temp"

WScript.Quit demoSF()

Function demoSF()
  demoSF = 0
  Dim aDSOrd : aDSOrd = getDSOrd(csDir, "%comspec% /c dir /A:-D /B /O:D /T:C """ & csDir & """")
  Dim oFile
  For Each oFile In aDSOrd
      WScript.Echo oFile.DateCreated, oFile.Name
  Next
End Function ' demoSF

Function getDSOrd(sDir, sCmd)
  Dim dicTmp : Set dicTmp = CreateObject("Scripting.Dictionary")
  Dim oExec  : Set oExec  = goWS.Exec(sCmd)
  Do Until oExec.Stdout.AtEndOfStream
     dicTmp(goFS.GetFile(goFS.BuildPath(sDir, oExec.Stdout.ReadLine()))) = Empty
  Loop
  If Not oExec.Stderr.AtEndOfStream Then
     WScript.Echo "Error:", oExec.Stderr.ReadAll()
  End If
  getDSOrd = dicTmp.Keys()
End Function

Output:

cscript 16895525.vbs
07.10.1998 15:31:34 TlbInf32.chm
..
09.10.2008 22:40:29 sqlce.sql
09.10.2008 22:40:29 gltsqlcopytest.sdf
05.11.2008 20:11:39 Vorfuehrung.class
..
28.03.2011 20:23:36 Program.cs
.
01.10.2012 10:10:10 KyXHDe.chm
shwartz
  • 631
  • 3
  • 13
  • 29
Ekkehard.Horner
  • 38,498
  • 2
  • 45
  • 96
  • 3
    As a suggestion: I'd add `/b` to the argument list to avoid needless detail in the output. – Ansgar Wiechers Jun 03 '13 at 16:39
  • I saw that option also and thought about it but wouldn't I have to output the results of the `dir` command to a file and then process that file? I tried using "Exec" but it looked as if it can only execute an executable and such (like "ping.exe") and it didn't work with `dir` (I couldn't find any `dir.com` file on Windows 7, maybe on Windows XP?). I'm worried that if I use create and use external files I might end up with some synchronization issues and locked files that can't be deleted, failing my script. How can the "dir" option be done without creating a file (by ">>")? – shwartz Jun 04 '13 at 07:28
  • Also, I can manage without setting the order of the files myself if I can be sure the "Files" collection returns them ordered by file name (so far, I didn't see any official documentation about it so I'm not assuming anything). – shwartz Jun 04 '13 at 07:29
  • So there is a "secret" documentation regarding the order of the `Files` collection. They should add that to the MSDN article. Too bad there's nothing simpler but that will do great. I was starting to regret choosing VBScript because it is already there and shouldn't require anything else installed. Thanks. – shwartz Jun 05 '13 at 10:51
0

This is similar to the accepted answer except that the file list is put into an array instead of a scripting dictionary. The order can be set by simply changing the Order constant to any order supported by the DIR command, such as /oen (order first by extension and then by name).

Const Folder = "C:\Test"
Const FileList = ".\FileList.txt"
Const Order = "/od /tc" 'Set DIR command order here
Const ForReading = 1

Set oWSH = CreateObject("WScript.Shell")
Set oFSO = CreateObject("Scripting.FileSystemObject")
oWSH.CurrentDirectory = oFSO.GetParentFolderName(WScript.ScriptFullName)

oWSH.Run "Cmd /c dir /b /a-d " & Order & " """ & Folder & "\*.*"">""" & FileList & """",0,True

FileContents = ""
On Error Resume Next
Set oFile = oFSO.OpenTextFile(FileList,ForReading)
FileContents = oFile.ReadAll
oFile.Close
On Error Goto 0
If FileContents="" Then
  MsgBox "No files found in folder:" & VBCRLF & VBCRLF & Folder,vbOKonly,WScript.ScriptName
  WScript.Quit
End If

ArrFiles = Split(FileContents,VBCRLF)
For i = 0 To UBound(ArrFiles)
  WScript.Echo ArrFiles(i)
Next

LesFerch
  • 1,540
  • 2
  • 5
  • 21