使用vbscript从一批相似的文件中复制最新文件

时间:2012-02-02 17:50:08

标签: vbscript

我不确定这是否可行。我甚至不知道从哪里开始。我有几千个文件,文件名的名称如下:

  

nnnnnnnnnnnnnnn.nyyyddmm.pdf(n =数字,yyyy =年,dd =天,mm =月)。

在这几千个文件中,有一些类似文件的文件具有相同的nnnnnnnnnnnnnnnnnn部分,但.yyyyddmm是不同的,以便表示文件的日期。 (这些批次相似的文件将在稍后合并在一起,但这对于这种情况并不重要)。

我的问题是,有没有办法比较相似文件的yyyyddmm部分,并将最新的日期文件复制到另一个文件夹?我需要将文件名中具有相同文件的最新日期的文件复制到另一个文件夹。

我遇到此问题的原因是因为我不确定是否可以比较部分文件名以查看哪一个实际上是具有最新日期的文件。我知道有一种方法可以通过查看日期修改日期来完成,但这并不总能给我带有最新日期的相似文件。

有什么想法?如果我能提供更多信息,请告诉我。

2 个答案:

答案 0 :(得分:2)

试图了解您的问题/规格。假设.pdf文件夹的文件循环导致:

Looking at "0000000000012345.20120402.pdf"
Looking at "0000000000012345.20120502.pdf"
Looking at "0000000000012348.20121702.pdf"
Looking at "0000000000012346.20120802.pdf"
Looking at "0000000000012347.20121002.pdf"
Looking at "0000000000012348.20121602.pdf"
Looking at "0000000000012347.20121302.pdf"
Looking at "0000000000012347.20121202.pdf"
Looking at "0000000000012345.20120202.pdf"
Looking at "0000000000012348.20121502.pdf"
Looking at "0000000000012346.20120602.pdf"
Looking at "0000000000012346.20120902.pdf"
Looking at "0000000000012348.20121402.pdf"
Looking at "0000000000012346.20120702.pdf"
Looking at "0000000000012347.20121102.pdf"
Looking at "0000000000012345.20120302.pdf"

Last file for 0000000000012345 is 0000000000012345.20120502.pdf
Last file for 0000000000012348 is 0000000000012348.20121702.pdf
Last file for 0000000000012346 is 0000000000012346.20120902.pdf
Last file for 0000000000012347 is 0000000000012347.20121302.pdf

识别要正确复制的文件?如果是,请说出来,我将在此处发布代码。

首先,您需要一个类来获取和存储放入文件名的信息:

' cut & store info about file(names) like "0000000000012347.20121202.pdf"
Class cCut
  Private m_sN  ' complete file name
  Private m_sG  ' group/number prefix part
  Private m_dtF ' date part; converted to ease comparisons
  Public Function cut(reCut, sFiNa)
    Set cut = Me ' return self/this from function
    Dim oMTS : Set oMTS = reCut.Execute(sFiNa)
    If 1 = oMTS.Count Then
       m_sN  = sFiNa
       Dim oSM : Set oSM = oMTS(0).SubMatches
       m_sG  = oSM(0)
       m_dtF = DateSerial(oSM(1), oSM(3), oSM(2))
    Else
       ' Err.Raise
    End If
  End Function ' cut
  Public Property Get G() : G = m_sG  : End Property ' G
  Public Property Get D() : D = m_dtF : End Property ' D
  Public Property Get N() : N = m_sN  : End Property ' N
End Class ' cCut

然后循环遍历.Files并检查存储在字典中的每个组的日期部分(用作键的数字前缀部分):

  ' The one and only .pdf folder - no recursion into subfolders!
  Dim sTDir : sTDir     = "..\data\test"
  ' dictionary to store the last/most recently used file for each group
  Dim dicG  : Set dicG  = CreateObject("Scripting.Dictionary")
  ' RegExp to cut/parse file names like "0000000000012345.20120402.pdf"
  Dim reCut : Set reCut = New RegExp
  reCut.Pattern = "^(\d{16})\.(\d{4})(\d{2})(\d{2})\.pdf$"
  Dim oFile
  For Each oFile In goFS.GetFolder(sTDir).Files
      WScript.Echo "Looking at", qq(oFile.Name)
      ' an oCut object for each file name
      Dim oCut : Set oCut = New cCut.cut(reCut, oFile.Name)
      If Not dicG.Exists(oCut.G) Then
         ' new group, first file, assume this is the latest
         Set dicG(oCut.G) = oCut
      Else
         ' found a better one for this group?
         If dicG(oCut.G).D < oCut.D Then Set dicG(oCut.G) = oCut
      End If
  Next
  WScript.Echo "-----------------------"
  Dim sG
  For Each sG In dicG.Keys
      WScript.Echo "Last file for", sG, "is", dicG(sG).N
  Next

WRT评论:

我的所有(ad hoc /概念验证)脚本都以

开头
Option Explicit
Dim goFS     : Set goFS = CreateObject( "Scripting.FileSystemObject" )

并包含一些处理不同方面/策略的函数,以解决常见问题/主题。当我在这里发布代码时,我将工作/测试代码复制/粘贴到函数框架的中间,如

' ============================================================================
goXPLLib.Add _
  "useDic02", "use a dictionary (Mark II)"
' ----------------------------------------------------------------------------
' ============================================================================
Function useDic02()
  useDic02 = 1 ' assume error

  ' The one and only .pdf folder - no recursion into subfolders!
  ...
  Next

  useDic02 = 0 ' success
End Function ' useDic02

(是的,有一个第一次尝试函数“useDic()”,它在第二个循环中存储了要处理的每个组的所有oCut;是的,我需要一个函数“createTestData()”设置/填写我的TDir)。有时我会马虎而忘记 goFS ,请接受我的道歉。

变量名称是实验的一部分。我过去常常提倡类型前缀的长变量名称,包括

Dim nIdx
For nIdx = 0 To UBound(aNames)
    aNames(nIdx) = ...
Next

其他人认为nIdx-alikes变量只是添加了一些错误的字母,但没有额外的含义,而且如果没有上下文就无法理解aNames-alikes如果你有,那么aN就会一样好余下的“从当前处理的文件中将波斯国王的名字与数据库中的名称进行比较”。

所以我想:鉴于文件名有3个有趣的方面(要复制的全名,要编号的前缀,要比较/决定的日期部分)以及之间有半个屏幕

  Private m_sN  ' complete file name

  Public Property Get N() : N = m_sN  : End Property ' N

并且假设您需要Cut对象的这3个属性才能在

中使用它
  Dim oCut : Set oCut = New cCut.cut(reCut, oFile.Name)
  If Not dicG.Exists(oCut.G) Then
     ' new group, first file, assume this is the latest
     Set dicG(oCut.G) = oCut
  Else
     ' found a better one for this group?
     If dicG(oCut.G).D < oCut.D Then Set dicG(oCut.G) = oCut

平均短时间记忆能否应对oCut.D?

显然不是。

复制所选文件:

假设您希望将文件复制到现有文件夹“.. \ data \ latest”,请使用

goFS.CopyFile goFS.BuildPath(sTDir, dicG(sG).N), "..\data\latest\", True

代替/除了行

WScript.Echo "Last file for", sG, "is", dicG(sG).N

我没想到.CopyFile会对相关的源码进行扼杀;所以考虑用* P * ath属性替换cCut类的* N * ame属性。

尝试使用

dicG(sG).Copy "..\data\latest\", True

结果:

Microsoft VBScript runtime error: Object doesn't support this property or method: 'dicG(...).Copy'

因为存储的对象不是文件(具有.Copy方法),而是cCuts(不存在)。

答案 1 :(得分:2)

我将如何处理它:

  1. 我会为每个唯一的数字部分创建一个单独的密钥字典。该值将是一个数组,其中所有文件名共享该键(因此共享唯一的数字部分)

  2. 对于字典中的每个键,我将遍历数组中的项目,搜索最近的日期。

  3. 方法:

    1. 获取文件
    2. 提取数字部分
    3. 查看该号码部分的密钥是否存在。如果没有为该数字创建一个键,并将空数组作为值
    4. 将文件名作为新项目添加到数组
    5. 循环到1.直到处理完所有文件

    6. 获取密钥

    7. 获取附加数组中的第一个文件。记住日期和arrayindex
    8. 获取下一个文件,如果日期高于记住日期,则将日期更新为此日期,并将arrayindex更新为此数组索引
    9. 循环到8.直到到达阵列的末尾
    10. 使用arrayindex存储文件作为该唯一编号的最新文件
    11. 循环到6.直到处理完所有键