Консультация № 175580
24.12.2009, 01:16
0.00 руб.
0 16 1
Здравствуйте Уважаемые эксперты. Помогите, пожалуйста, написать vbs скрипт.
Который бы выводил размер всех файлов указного расширения на указанном диске в окне.
Вот до чего я дошел:
Код:
Set objArgs = WScript.Arguments
call ShowDriveInfo(objArgs(0))

Sub ShowDriveInfo(drvPath)
Dim fso, drv, s, fil,f1,f
Set fso = CreateObject("Scripting.FileSystemObject")
Set drv = fso.GetDrive(fso.GetDriveName(drvPath))
Set f = fso.GetFolder(objArgs(0))
Set fc = f.SubFolders
For Each f1 in fc
s = s & f1.size
s = s & f1.name
s = s & VbCrLf
Next
msgbox s
End Sub

Но дело в том, что как сложить все эти размеры, и как именно указанный тип выбрать и все это мне остается не понятно.
Я думал что нужно как то с оператором like. Например: if "ObjArgs(1)" like f1.name Then....
Но в таком случае жаловалось на ошибку.
Заранее благодарен.

Обсуждение

давно
Модератор
137394
1850
24.12.2009, 08:21
общий
Dimon4ik:
В VBS Like не работает. Там надо регулярное выражение. А Вам надо итоговый размер файлов во всех подпапках? Так, с налёта, надо писать подпрограмму с рекурсией. И Именно на VBS? Команда командного окна
dir *.mp3 /A /s
в конце концов покажет искомую информацию
Об авторе:
Понеже не словес красных бог слушает, но дел наших хощет
давно
Модератор
137394
1850
24.12.2009, 12:18
общий
это ответ
Здравствуйте, Dimon4ik. Вот решение. Оно позволяет посчитать суммарный размер файлов по указанной в скрипте маске в папке и содержащихся в ней подпапках.
Код:

Set Argum = WScript.Arguments

If Argum.Count = 0 Then
a = MsgBox("Скрипт запущен без аргументов")
Else

' Подсчёт суммарного размера файлов в директории и всех поддиректориях по маске
' Исходные данные

iiiDir = Argum(0) ' Директория

Maska = "^.*\.xls$" ' Маска файла

' ---------------------------------------------

Set FSO = CreateObject("Scripting.FileSystemObject")

nFiles=0
Mess = SizeFilesDir(iiiDir, Maska)

Call AllFolders(iiiDir, Maska)

a = MsgBox("Директория: " + iiiDir + vbCrLf + "Маска: " + Maska + vbCrLf + "Суммарный размер файлов: " + CStr(Mess) + vbCrLf + "Количество файлов: " + CStr(nFiles))

End If


Sub AllFolders(inDir, inMaska) ' ---------------------------------------------
' Wscript.Echo inDir
Set F = FSO.GetFolder(inDir)
Set SubF = F.SubFolders

For Each Folder In SubF
' Wscript.Echo Folder.Name
Mess = Mess + SizeFilesDir(inDir + "" + Folder.Name, inMaska)
Call AllFolders(inDir + "" + Folder.Name, inMaska)

Next

End Sub


Function SizeFilesDir(iDir, iMaska) ' ---------------------------------------------
' Подсчет длины файлов в директории по маске
' iDir - ' Имя директории (без \ на конце)
' iMaska - ' Маска файлов (например "*.exe")

iSize = 0

Set Tdir = FSO.GetFolder(iDir)
Set AllFiles = Tdir.Files

' Set RE = CreateObject("VBscript.RegExp") ' Так Тоже можно
Set Re = New RegExp

Re.Pattern = iMaska
Re.MultiLine = False
Re.Global = True
Re.IgnoreCase = True

For Each iFile In AllFiles
If Re.Test(iFile.Name) Then
iSize=iSize+iFile.Size
nFiles=nFiles+1
End If
Next

SizeFilesDir = iSize

End Function

Сохраните код в файл с расширением .vbs в Windows-кодировке, например SumSizeFile.vbs
Запускайте его с аргументом, например:

SumSizeFile.vbs "F:"
SumSizeFile.vbs "C:\Program Files"

Проверил, работает, по результатам совпадает с результатами команды Dir

Скрипт можно взять в прикреплённом файле. Только переименуйте его в правильное расширение.

Вот код позволяющий вводить имя директории и расширение, например
SumSizeFile.vbs "D:" "XLS"
В предыдущем скрипте может возникнуть проблема при работе, когда в указанной папке есть подпапка, для которой у Вас нет доступа, например "System Volume Information"
В приведенном коде это учтено. Можно взять его SumSizeFile.vbs (4.1 кб)
Код:
' ---------------------------------------------------------------------------
' Скрипт подсчитывает суммарный размер файлов по маске в папке и подпапках
' Вызов скрипта, например:
' SumSizeFile.vbs "F:" "XLS"
' SumSizeFile.vbs "C:\Program Files" "Exe"
' При наличии пробелов аргумент обязательно взять в кавычки
' ---------------------------------------------------------------------------

Set Argum = WScript.Arguments

If Argum.Count <2 Then ' Если при вызове скрипта кол-во аргументов <2 ничего не делаем
a = MsgBox("Скрипт запущен без аргументов")
Else

iiiDir = Argum(0) ' Директория (берём из аргумента)

Maska = "^.*\." + Argum(1) + "$" ' Формируем строку для регулярного выражение для маски файла (из аргумента)

' ---------------------------------------------

Set FSO = CreateObject("Scripting.FileSystemObject") ' Создаём объект для доступа к файловой системе

nFiles=0 ' Начальное значение кол-ва файлов
Mess = SizeFilesDir(iiiDir, Maska)
' Подсчитываем файлы и их длину в корне указанной директории
Call AllFolders(iiiDir, Maska) ' Подсчитываем файлы и их длину во всех поддиректориях

a = MsgBox("Директория: " + iiiDir + vbCrLf + "Маска: " + Maska + vbCrLf + "Суммарный размер файлов: " + CStr(Mess) + vbCrLf + "Количество файлов: " + CStr(nFiles))

End If


Sub AllFolders(inDir, inMaska) ' ---------------------------------------------
' Процедура рекурентно подсчитывает файлы и их длину в директории и поддиректориях
' inDir - путь директории
' inMaska - регулярное выражение с маской файлов
' Wscript.Echo inDir

On Error Resume Next ' Обработаем ситуацию, если встретилась директория без доступа
Set F = FSO.GetFolder(inDir) ' Создаём объект для доступа к директории
If Err.Number = 0 Then
Set SubF = F.SubFolders ' Создаём коллекцию поддиректорий в указ директории

For Each Folder In SubF ' Просматриваем каждый элемент коллекции (все директории)
' Wscript.Echo Folder.Name
Mess = Mess + SizeFilesDir(inDir + "" + Folder.Name, inMaska) ' Насуммируем число файлов и их длину
Call AllFolders(inDir + "" + Folder.Name, inMaska) ' Рекурентно Просматриваем каждый элемент коллекции (все директории)

Next

End If

End Sub


Function SizeFilesDir(iDir, iMaska) ' ---------------------------------------------
' Подсчет длины файлов в директории по маске
' iDir - ' Имя директории (без \ на конце)
' iMaska - ' Маска файлов (например "*.exe")

iSize = 0

On Error Resume Next ' Обработаем ситуацию, если встретилась директория без доступа

Set Tdir = FSO.GetFolder(iDir) ' Создаём объект для доступа к текущей директории
If Err.Number = 0 Then

Set AllFiles = Tdir.Files ' Для текущей директории создаём коллекцию файлов

' Set RE = CreateObject("VBscript.RegExp") ' Так Тоже можно

Set Re = New RegExp ' Создаём экземпляр регулярного выражения

Re.Pattern = iMaska ' Задаём маску
Re.MultiLine = False ' Текст однострочный
Re.Global = True ' будем проходить всю строку
Re.IgnoreCase = True ' игнорируем регистр символов

For Each iFile In AllFiles ' Просматриваем файлы в директории
If Re.Test(iFile.Name) Then ' Проверяем имя файла на соответствие рег выражению
iSize=iSize+iFile.Size ' Насуммируем размеры файлов
nFiles=nFiles+1 ' Насуммируем кол-во файлов
End If
Next

End If

SizeFilesDir = iSize

End Function

В дополнение к ответу приведу решение с помощью командного файла. Решение основано на том, что суммарная информация по файлам содержится в предпоследней строке выдачи команды Dir
Код:
echo off
rem ----------------------------------------------------------------
rem В аргументе при вызове путь и имя файла или маска файла
rem Например (если в имени или пути есть пробел, обязательны кавычки
rem SumSizeFile.bat "C:\Program Files\*.xls"
rem SumSizeFile.bat C:\*.xls
rem ----------------------------------------------------------------

if "%1"=="" GoTo WithOut

Set ComDir=dir /s %1

Set S1=''
Set S2=''

For /F "usebackq delims==" %%a In (`%ComDir%`) Do Call :Stroka2 "%%a"

Call :Rezult %1 %S2%

GoTo End

rem ----------------------------------------------------------------
:Stroka2

Set S2=%S1%
Set S1=%1

GoTo End

rem ----------------------------------------------------------------
:Rezult
Echo ---------------------------------------------------------------
Echo %~1
Echo %~2
Echo ---------------------------------------------------------------
pause
GoTo End

:WithOut
Echo !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Echo Не указан аргумент командного файла
Echo !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
pause

:End

Прикрепленные файлы:
5
Большое Вам спасибо, уже много раз Вы меня выручаете с различного рода задачами!<br>Отличный код, описание, а также спасибо за выложенные Вами файлы со скриптами!
Об авторе:
Понеже не словес красных бог слушает, но дел наших хощет
Неизвестный
24.12.2009, 13:28
общий
В VBS Like не работает.

Понял. Спасибо, а то я и дальше бы думал что я в синтаксисе этого оператора не правильно пишу...
Спасибо большое за скрипт.
Только у меня возникла проблема...
Сейчас пробую его запустить. Переименовал как надо, с командной строки посылаю аргумент
Код:
D:\>W.vbs c:\

D:\>W.vbs C:\

D:\>W.vbs C:\*.txt

D:\>W.vbs C:\ *.txt

D:\>w.vbs D:\

D:\>w.vbs E:\

Как только не посылаю аргументы - он не запускается. Вообще ничего не происходит. А когда посылаю аргумент диск D:
Код:
Сценарий D:\W.vbs
Строка:61
Символ:5
Ошибка:Разрешение отклонено
Код:800А0046
Источник: Ошибка выполнения Microsoft VBScript


И так у меня уже в нескольких скриптах, которые у друзей нормально работают.

А когда пишу так:
D:\>w.vbs D:\WORK\ *.jpg
То выдает:
Код:
Директория D:\WORK\
Маска: ^.*\.xls$
Суммарный размер файлов: 0
Количество файлов:0


В общем немного не могу разобраться...
Неизвестный
24.12.2009, 13:39
общий
Megaloman:
Сейчас начали поочереди срабатывать те скрипты что я 10 мин назад запустил. Все выдают ошибку такого типа:
Код:
Сценарий D:\W.vbs
Строка:61
Символ:5
Ошибка:Разрешение отклонено
Код:800А0046
Источник: Ошибка выполнения Microsoft VBScript
давно
Модератор
137394
1850
24.12.2009, 14:04
общий
В параметрах только имя директории. Я не предусматривал в аргументах маску. Пример вызова я Вам привёл в ответе Где-то Вам не хватает прав на выполнение скрипта.
Об авторе:
Понеже не словес красных бог слушает, но дел наших хощет
Неизвестный
24.12.2009, 14:23
общий
Megaloman:
Пишу так, как вы написали, только свое подставляю.
Ищет только при указании папки. Если указывать жесткий диск и все то не работает. Выдает ошибку о которой я уже говорил.
давно
Модератор
137394
1850
24.12.2009, 16:40
общий
Dimon4ik:
Вот код позволяющий вводить имя директории и расширение, например
SumSizeFile.vbs "D:" "XLS"
Похоже, проблема возникает тогда, когда в указанной папке есть подпапка, для которой у Вас нет доступа, например "System Volume Information"
В приведенном коде это учтено. Можно взять его SumSizeFile.vbs (2.1 кб)
Код:
 Set Argum = WScript.Arguments

If Argum.Count <2 Then
a = MsgBox("Скрипт запущен без аргументов")
Else

' Подсчёт суммарного размера файлов в директории и всех поддиректориях по маске
' Исходные данные

iiiDir = Argum(0) ' Директория

Maska = "^.*\." + Argum(1) + "$" ' Маска файла

' ---------------------------------------------

Set FSO = CreateObject("Scripting.FileSystemObject")

nFiles=0
Mess = SizeFilesDir(iiiDir, Maska)

Call AllFolders(iiiDir, Maska)

a = MsgBox("Директория: " + iiiDir + vbCrLf + "Маска: " + Maska + vbCrLf + "Суммарный размер файлов: " + CStr(Mess) + vbCrLf + "Количество файлов: " + CStr(nFiles))

End If


Sub AllFolders(inDir, inMaska) ' ---------------------------------------------
' Wscript.Echo inDir
On Error Resume Next
Set F = FSO.GetFolder(inDir)
If Err.Number = 0 Then
Set SubF = F.SubFolders

For Each Folder In SubF
' Wscript.Echo Folder.Name
Mess = Mess + SizeFilesDir(inDir + "" + Folder.Name, inMaska)
Call AllFolders(inDir + "" + Folder.Name, inMaska)

Next

End If
End Sub


Function SizeFilesDir(iDir, iMaska) ' ---------------------------------------------
' Подсчет длины файлов в директории по маске
' iDir - ' Имя директории (без \ на конце)
' iMaska - ' Маска файлов (например "*.exe")

iSize = 0

On Error Resume Next

Set Tdir = FSO.GetFolder(iDir)
If Err.Number = 0 Then

Set AllFiles = Tdir.Files

' Set RE = CreateObject("VBscript.RegExp") ' Так Тоже можно
Set Re = New RegExp

Re.Pattern = iMaska
Re.MultiLine = False
Re.Global = True
Re.IgnoreCase = True

For Each iFile In AllFiles
If Re.Test(iFile.Name) Then
iSize=iSize+iFile.Size
nFiles=nFiles+1
End If
Next

End If

SizeFilesDir = iSize

End Function

Об авторе:
Понеже не словес красных бог слушает, но дел наших хощет
Неизвестный
24.12.2009, 16:51
общий
Megaloman:
А сколько скрипт по времени должен выполняться, если на диске занято примерно 25 Гб. Кол-во мелких фалов - не очень много.
давно
Модератор
137394
1850
24.12.2009, 16:58
общий
Вообще-то мне показалось, что медленно (по сравнению с командой Dir). Как ускорить -пока не знаю Можно попробовать как-то задействовать Dir, но пока не готов заняться. Возьмите самую последнюю версию скрипта (ссылка в предыдущем сообщении - там корректнее обрабатываются ошибки - спешка ...
Об авторе:
Понеже не словес красных бог слушает, но дел наших хощет
Неизвестный
24.12.2009, 17:00
общий
Megaloman:
О! Заработало. Отлично!
У меня будет еще одна маленькая просьба- пожалуйста, Вы не могли бы добавить комментариев еще чуть чуть.
Например такие строки как :
Код:
   Re.Pattern = iMaska
Re.MultiLine = False
Re.Global = True
Re.IgnoreCase = True

On Error Resume Next

SubF

Maska = "^.*\." + Argum(1) + "$"
If Err.Number = 0 Then

и прочее.
Хотя бы немного.
Пожалуйста.
давно
Модератор
137394
1850
24.12.2009, 17:01
общий
Dimon4ik:
Добавлю, но не мигом, занят пока
Об авторе:
Понеже не словес красных бог слушает, но дел наших хощет
Неизвестный
24.12.2009, 17:03
общий
Можно попробовать как-то задействовать Dir, но пока не готов заняться.

Не стоит. Отлично! Вы мне и так здорово помогли. Такой скрипт отлично подойдет.
давно
Модератор
137394
1850
24.12.2009, 19:25
общий
Dimon4ik:
Вот скрипт с описаниями по тексту
Код:
' ---------------------------------------------------------------------------
' Скрипт подсчитывает суммарный размер файлов по маске в папке и подпапках
' Вызов скрипта, например:
' SumSizeFile.vbs "F:" "XLS"
' SumSizeFile.vbs "C:\Program Files" "Exe"
' При наличии пробелов аргумент обязательно взять в кавычки
' ---------------------------------------------------------------------------

Set Argum = WScript.Arguments

If Argum.Count <2 Then ' Если при вызове скрипта кол-во аргументов <2 ничего не делаем
a = MsgBox("Скрипт запущен без аргументов")
Else

iiiDir = Argum(0) ' Директория (берём из аргумента)

Maska = "^.*\." + Argum(1) + "$" ' Формируем строку для регулярного выражение для маски файла (из аргумента)

' ---------------------------------------------

Set FSO = CreateObject("Scripting.FileSystemObject") ' Создаём объект для доступа к файловой системе

nFiles=0 ' Начальное значение кол-ва файлов
Mess = SizeFilesDir(iiiDir, Maska)
' Подсчитываем файлы и их длину в корне указанной директории
Call AllFolders(iiiDir, Maska) ' Подсчитываем файлы и их длину во всех поддиректориях

a = MsgBox("Директория: " + iiiDir + vbCrLf + "Маска: " + Maska + vbCrLf + "Суммарный размер файлов: " + CStr(Mess) + vbCrLf + "Количество файлов: " + CStr(nFiles))

End If


Sub AllFolders(inDir, inMaska) ' ---------------------------------------------
' Процедура рекурентно подсчитывает файлы и их длину в директории и поддиректориях
' inDir - путь директории
' inMaska - регулярное выражение с маской файлов
' Wscript.Echo inDir

On Error Resume Next
Set F = FSO.GetFolder(inDir) ' Создаём объект для доступа к директории
If Err.Number = 0 Then
Set SubF = F.SubFolders ' Создаём коллекцию поддиректорий в указ директории

For Each Folder In SubF ' Просматриваем каждый элемент коллекции (все директории)
' Wscript.Echo Folder.Name
Mess = Mess + SizeFilesDir(inDir + "" + Folder.Name, inMaska) ' Насуммируем число файлов и их длину
Call AllFolders(inDir + "" + Folder.Name, inMaska) ' Рекурентно Просматриваем каждый элемент коллекции (все директории)

Next

End If

End Sub


Function SizeFilesDir(iDir, iMaska) ' ---------------------------------------------
' Подсчет длины файлов в директории по маске
' iDir - ' Имя директории (без \ на конце)
' iMaska - ' Маска файлов (например "*.exe")

iSize = 0

On Error Resume Next

Set Tdir = FSO.GetFolder(iDir) ' Создаём объект для доступа к текущей директории
If Err.Number = 0 Then

Set AllFiles = Tdir.Files ' Для текущей директории создаём коллекцию файлов

' Set RE = CreateObject("VBscript.RegExp") ' Так Тоже можно

Set Re = New RegExp ' Создаём экземпляр регулярного выражения

Re.Pattern = iMaska ' Задаём маску
Re.MultiLine = False ' Текст однострочный
Re.Global = True ' будем проходить всю строку
Re.IgnoreCase = True ' игнорируем регистр символов

For Each iFile In AllFiles ' Просматриваем файлы в директории
If Re.Test(iFile.Name) Then ' Проверяем имя файла на соответствие рег выражению
iSize=iSize+iFile.Size ' Насуммируем размеры файлов
nFiles=nFiles+1 ' Насуммируем кол-во файлов
End If
Next

End If

SizeFilesDir = iSize

End Function

Забыл описать On Error - это обработка ошибочных ситуаций, в этом скрипте позволяет обойти директории, к которым нет доступа
Об авторе:
Понеже не словес красных бог слушает, но дел наших хощет
Неизвестный
25.12.2009, 03:20
общий
чуть дополню
т.к. проверка идет только на расширение файла, можно обойтись без регулярных выражений:
или
If FSO.GetExtensionName(File) = Extension Then...

или вообще
If StrComp(Right(File, Len(Extension) + 1), "." + Extension, 1) = 0 Then...

должно выполняться быстрее...

давно
Модератор
137394
1850
25.12.2009, 06:09
общий
HookEst:
Вы, наверное, правы, но изначально я вообще делал скрипт безотносительно к тому, что будет только расширение. Я не планировал расширение вносить в аргумент при вызове. Я считал, что будут искаться файлы в изменяемых директориях по фиксированной маске. С этой точки зрения рег выражение гибче. Поэтому в самом первом решении я жестко забил маску в скрипте. Единственное, не указал в ответе, что её надо руками подправить - раз клиент пишет сам скрипты для него это не должно быть проблемой.
Об авторе:
Понеже не словес красных бог слушает, но дел наших хощет
давно
Модератор
137394
1850
25.12.2009, 14:12
общий
Добавил в ответ решение на основе .bat файла
Об авторе:
Понеже не словес красных бог слушает, но дел наших хощет
Форма ответа