|
补一个方法
如何列出文件夹及其所有子文件夹中的文件?
问:
您好,脚本专家!如何列出某个文件夹中的所有文件以及该文件夹的所有子文件夹中的所有文件?
-- MA
答:
您好,MA。有很多用户提出过这个问题,我们还没来得及作出解答。这是因为,这个问题还没有一个既有效又简便的解决办法:能够完成这一任务的脚本注定会有些不易理解,也无法通过本专栏惯用的简洁明了的方式进行解决。从另一方面来说,客户永远是正确的:如果您们需要一个能够列出某个文件夹中的所有文件以及该文件夹的所有子文件夹中的所有文件的脚本,我们还有什么可说的呢?
着手编写脚本前,必须先解决两个问题。第一,需要选择一种脚本技术。WMI、FileSystemObject 及 Shell 对象都能列出文件夹中的文件以及文件夹中的子文件夹。不过,这些技术都没有能够自动列出这些子文件夹中文件的机制(更不必说可能存在的再下一级文件夹了)。使用上述任何一种技术都可以达到目的,但都不是非常容易。
我们倾向于使用 WMI。使用它编写的脚本可能比使用 FileSystemObject 或 Shell 对象编写的类似脚本复杂一些,但 WMI 脚本的优点是,在本地计算机上检索此类信息与从远程计算机中检索同样方便。而 FileSystemObject 或 Shell 对象都做不到这一点。我们看重的是 WMI 的灵活性。
第二,我们注意到,所有这些脚本技术都没有完成以下操作的内置方法:循环访问文件夹,列出文件名,然后自动循环访问所有子文件夹并列出其中的文件。因此,需要使用"递归函数"来执行这项任务。对递归进行说明超出了本专栏的讨论范围;有关简要说明,请参阅 Microsoft Windows 2000 脚本编写指南。只需说我们要创建一个可以根据需要多次调用自身的函数就够了。换句话说,如果我们有可以访问某个文件夹并列出其中所有文件的函数,则该函数可以调用自身来访问子文件夹并列出其中的所有文件,然后再次调用自身来访问再下一级文件夹。很难以直观的方式来说明这一点,但这种方法的确奏效。
它还会产生一个新问题,我们稍后再进行讨论。我们先来看一个脚本,它的作用是列出某个文件夹及其所有子文件夹(但这第一个示例脚本并未列出这些文件夹中的任何文件):
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
strFolderName = "c:\scripts"
Set colSubfolders = objWMIService.ExecQuery _
("Associators of {Win32_Directory.Name='" & strFolderName & "'} " _
& "Where AssocClass = Win32_Subdirectory " _
& "ResultRole = PartComponent")
For Each objFolder in colSubfolders
GetSubFolders strFolderName
Next
Sub GetSubFolders(strFolderName)
Set colSubfolders2 = objWMIService.ExecQuery _
("Associators of {Win32_Directory.Name='" & strFolderName & "'} " _
& "Where AssocClass = Win32_Subdirectory " _
& "ResultRole = PartComponent")
For Each objFolder2 in colSubfolders2
strFolderName = objFolder2.Name
Wscript.Echo objFolder2.Name
GetSubFolders strFolderName
Next
End Sub
'---------------------------------------------------------------------------
以上脚本的作用是使用"AssociatorsOf"查询来获取文件夹 C:\Scripts 的所有子文件夹的列表。我们的查询所要表达的基本意思是:给我提供与目录 C:\Scripts 相关的所有项目的列表,但前提是这些项目是子目录("Where AssocClass = Win32_Subdirectory")。
此脚本获取的是所有顶级子文件夹的列表:例如,C:\Scripts\Folder1 和 C:\Scripts\Folder2。它不能获取任何下一级文件夹;此查询无法返回像 C:\Scripts\Folder1\SubfolderA 之类的文件夹。要获取这些下一级子文件夹(子文件夹的子文件夹),我们需要使用递归查询。子例程"GetSubFolders"可以实现这个目的。我们将找到的每个子文件夹的名称(如 C:\Scripts\Folder1 和 C:\Scripts\Folder2)逐一传递给该子例程,使之查询这些子文件夹中是否有下一级子文件夹。如果有任何下一级子文件夹,该函数将自动调用自身并查找是否有再下一级子文件夹。
感到困惑不解吗?不必沮丧;很多人都会有这种感觉。但不要担心,只需让代码保持原样并运行即可。要搜索其他文件夹(即 C:\Scripts 以外的文件夹),只需更改包含要搜索的文件夹的变量值即可。例如,如果要搜索 C:\Windows,请使用以下这行代码:
strFolderName = "c:\windows"
那么,如何列出所有这些文件夹中的文件?从现在开始,情况确实变得更复杂了。这是因为,我们需要再执行一个查询:我们使用一个查询来获取所有子文件夹的名称,然后使用另一个查询获取每个文件夹中的文件集合。这第二个查询恰好与以下内容非常相似:
Set colFiles = objWMIService.ExecQuery _
("Select * from CIM_DataFile where Path = '" & strPath & "'")
这还不算太复杂,但以下情况就不同了:在此类查询中,必须"转义"在文件路径中出现的 \(使用两个 \\)。不能在查询中使用"C:\Scripts\Folder1\";而必须使用"C:\\Scripts\\Folder1\\"。您会发现,脚本中的代码将每个 \ 都替换为 \\;在此类查询中引用文件路径时,这正是我们需要做的。脚本中相当大一部分内容专用于转换文件夹路径名,以使它们可以在查询中使用。
注意事项就讲这么多。以下便是每位用户都想一睹为快的脚本:
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
strFolderName = "c:\scripts"
Set colSubfolders = objWMIService.ExecQuery _
("Associators of {Win32_Directory.Name='" & strFolderName & "'} " _
& "Where AssocClass = Win32_Subdirectory " _
& "ResultRole = PartComponent")
Wscript.Echo strFolderName
arrFolderPath = Split(strFolderName, "\")
strNewPath = ""
For i = 1 to Ubound(arrFolderPath)
strNewPath = strNewPath & "\\" & arrFolderPath(i)
Next
strPath = strNewPath & "\\"
Set colFiles = objWMIService.ExecQuery _
("Select * from CIM_DataFile where Path = '" & strPath & "'")
For Each objFile in colFiles
Wscript.Echo objFile.Name
Next
For Each objFolder in colSubfolders
GetSubFolders strFolderName
Next
Sub GetSubFolders(strFolderName)
Set colSubfolders2 = objWMIService.ExecQuery _
("Associators of {Win32_Directory.Name='" & strFolderName & "'} " _
& "Where AssocClass = Win32_Subdirectory " _
& "ResultRole = PartComponent")
For Each objFolder2 in colSubfolders2
strFolderName = objFolder2.Name
Wscript.Echo
Wscript.Echo objFolder2.Name
arrFolderPath = Split(strFolderName, "\")
strNewPath = ""
For i = 1 to Ubound(arrFolderPath)
strNewPath = strNewPath & "\\" & arrFolderPath(i)
Next
strPath = strNewPath & "\\"
Set colFiles = objWMIService.ExecQuery _
("Select * from CIM_DataFile where Path = '" & strPath & "'")
For Each objFile in colFiles
Wscript.Echo objFile.Name
Next
GetSubFolders strFolderName
Next
End Sub
'---------------------------------------------------------------------------
我们曾说过脚本比较复杂。不过还真管用!此脚本所执行的操作如下:绑定到 C:\Scripts 文件夹并回显其中的所有文件的名称,然后获取 C:\Scripts 中所有子文件夹的列表。接着循环访问子文件夹集合,并为每个子文件夹调用递归函数 GetSubFolders。该函数将列出子文件夹中的所有文件,然后检查该子文件夹是否有下一级子文件夹。如果有,将再次调用递归函数;继续重复执行这一过程,直至无法再继续为止,即列出了 C:\Scripts 及其所有子文件夹中的所有文件。
明天,可真该回头探讨一个容易解决的问题了。有哪位想知道如何使用脚本来获取本地计算机的名称吗?
--------------------------------------------------------------------------------
|
评分
-
1
查看全部评分
-
|