Имя: Пароль:
1C
1C 7.7
v7: ФС.НайтиСледующийФайл - как исключить заход в подпапку?
0 Vladal
 
27.01.12
18:56
Понимаю, что пятница. конец рабочего дня.

Перебираю папку с файлами методом ФС.НайтиПервыйФайл и ФС.НайтиСледующийФайл.

Довольно удобная штука, т.к. рекурсивно заходит в подпапки и читает все файлы оттуда.

   Файл = ФС.НайтиПервыйФайл(Каталог+"\*.ert");
   Пока ПустаяСтрока(Файл) = 0 Цикл
       ТЗСписокФайлов.НоваяСтрока();
       ТЗСписокФайлов.Файл = Файл;
       
       ...
       
       Файл = ФС.НайтиСледующийФайл();
   КонецЦикла;

Замер производительности ругается именно на процедуру поиска файлов.
Думал выбрать все файлы и отсеивать только *.ert, но приросту никакого - 1С затрачиывает дополнительное время на сравнение условий.

Как исключить эту конкретную подпапку, в которой более 20'000 файлов и там явно нет *.ert?
1 zak555
 
27.01.12
18:56
продолжить ?
2 Гот
 
27.01.12
18:57
Храни ерт в другом месте
3 Mikeware
 
27.01.12
18:58
dir'ом в файл, файл разбирать :-)
4 Vladal
 
27.01.12
19:03
(3) Не пойдёт. Надо найти все обработки во всех подпапках рекурсивно.
Но тут попадается та папка с ненужными мне файлами, ФС её читает и всё.
Это особенность движка ФС или каким способом еще можно?
5 Vladal
 
27.01.12
19:04
О!
Эврика!
Может WSH задействовать?
6 Vladal
 
27.01.12
19:35
Вроде как нашел способ. Теперь вместо сообщения надо файл в список совать.
А как - тупонька не соображает:

On Error Resume Next
Set objService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\CIMV2")
If Err.Number <> 0 Then
   WScript.Echo Err.Number & ": " & Err.Description
   WScript.Quit
End If
Set colFiles = objService.ExecQuery("SELECT Name FROM CIM_DataFile WHERE " & _
   "Drive = 'C:' AND Path LIKE '\\%' AND Extension = 'ERT'")
For Each objFile In colFiles
   WScript.Echo objFile.Name
Next
WScript.Echo "Всего файлов: " & colFiles.Count
7 FN
 
27.01.12
20:01
Два прохода - первым собираешь папки, вторым файлы
8 Vladal
 
29.01.12
12:24
(7) Так и есть. Но ФС.НайтиСледующийФайл() лопатит опять весь диск и в том числе ненужную папку.
К WSH руки пока не дотянулись, но он сработал значительно быстрее.
9 ДенисЧ
 
29.01.12
12:26
(8) гонишь. НайтиСледующийФайл вызывает системную функцию.
10 Vladal
 
29.01.12
12:27
(9) Замером производительности замерял.
11 Vladal
 
29.01.12
12:30
У меня 112 секунд процедура поиска папок занимает и 146 секунд складирование файлов:

Процедура ЗаполнитьКат()
   Перем д;
   
   Каталоги.УдалитьВсе();
   Файл = ФС.НайтиПервыйФайл(Каталог+"\*.");
   Пока ПустаяСтрока(Файл) = 0 Цикл
       ФС.АтрибутыФайла(Каталог+"\"+Файл,, д);
       Если (Сред( д, 4, 1) = "1") И (Файл <> ".") И (Файл <> "..") Тогда
           Каталоги.ДобавитьЗначение(Файл);
       КонецЕсли;
       Файл = ФС.НайтиСледующийФайл();
   КонецЦикла;
   
   н = СтрДлина(Каталог);
   Пока н > 0 Цикл
       Если Сред( Каталог, н, 1) = "\" Тогда
           ИмяКаталога = Прав(Каталог, СтрДлина(Каталог)-н);
           Прервать;
       КонецЕсли;
       н = н-1;
   КонецЦикла;
КонецПроцедуры // ЗаполнитьКат
12 FN
 
29.01.12
14:30
C:\>dir /AD /S /B >dirs.txt

потом проход по списку с помощью ФС.НайтиПервыйФайл(Каталог+"\*.ert");
13 Ковычки
 
29.01.12
14:40
Shell.Application + Filter
14 Vladal
 
29.01.12
15:06
(13) Вот про этот самый Shell.Application  рою.
15 Vladal
 
29.01.12
15:08
(12) О! dir /AD /S /B что-то прояснило
16 Torquader
 
29.01.12
18:29
Set Fso=CreateObject(Scripting.FileSystemObject)
Set d=Fso.GetFolder(PathToFolder)
For Each f in d.Files
;перебираем файлы
Next
For Each p In d.SubFolders
;перебираем вложенные директории
Next

Что касается работы с директорией, где много файлов, то любая системная функция при пролистывании или выводит содержимое всей директории сразу или при каждом вызове делает перебор заново, чтобы выбрать следующий по номеру файл.
17 Vladal
 
29.01.12
18:36
(16) Вот мне-то как раз и надо тут папку с многофайлами пропустить.
Megj в неё не заходить.

Я согласен в первый раз прочитать все подпапки, составить их список и потом заходить в них.

Пример:

КорневаяПапка
+ Подпапка1
+ Подпапка2
+ Подпапка3
+ Подпапка4 --- вот эту надо пропускать
+ Подпапка5
+ Подпапка6

Составили список файлов, потом в каждую кроме 4-й заходим и читаем список вложенных файлов.
18 Vladal
 
29.01.12
18:51
Я составляю список подпапок, пропуская Подпапку4, потом по списку иду и рекурсивно создаю список файлов именно этих подпапок.
Таким образом будет читаться содержимое только "Правильные" подпапки, а нехоршка пропускается.
19 rs_trade
 
29.01.12
18:58
если возможно, именовать папки так, что бы понятно было где искать, а что пропускать.
20 Torquader
 
29.01.12
19:27
(19) а что VbScript.RegExp не поможет отличить Подпапка4 от всех остальных.
Другое дело, что в директории с внешними формами хранить ещё кучу всего явно нехорошо.
21 Cthulhu
 
29.01.12
19:47
КомандаСистемы - dir - скинуть в какой надо файл в каком надо формате и пропарсить...
22 Vladal
 
30.01.12
11:15
(20) Если может, то как? Я вот пока еще не нашел способ.
23 Vladal
 
30.01.12
11:15
(21) Хороший вариант, был немного выше, оставил на закуску.
24 1Сергей
 
30.01.12
11:20
ФС.АтрибутыФайла(<?>,,,,,,); не подходит?
25 FN
 
30.01.12
11:37
(23) можешь взять сразу готовый список файлов:
dir *.ert /S /B >нужныйтекстовик.txt
26 Vladal
 
30.01.12
12:07
(24) Атрибуты есть, я их читаю в первом проходе, когда собираю каталоги.
Но беда, что ФС.НайтиСледующийФайл() ищет всё.

Так что самы быстрый вариант поперебору в парсинге dir
27 Ковычки
 
30.01.12
12:45
так ?

Процедура РекурсивноПапки(Корень=".",Сп)
   Если ПустоеЗначение(Сп)=1 Тогда
       Сп=СоздатьОбъект("СписокЗначений");
   КонецЕсли;
   ХТМЛ = СоздатьОбъект("htmlfile");
   ХТМЛ.Open("text/html");
   //<-- Подготовим нужные методы
   ХТМЛ.Write("<script>
   |var ХТМЛ;
   |Новый=function(x,y){return new x(y)}
   |</script>");
   Это=ХТМЛ.documentElement.document.script;
   Шел=СоздатьОбъект("Shell.Application");
   Темы=Шел.NameSpace(Корень).Items();
   Темы.Filter(64+128,"*.ert");
   Файлы=Это.Новый(Это.Enumerator,Темы);
   Пока Файлы.atEnd(0)=0 Цикл
       Сп.ДобавитьЗначение(Файлы.item(0).Path);
       Сообщить(Файлы.item(0).Path);
       Файлы.moveNext(0);
   КонецЦикла;
   Темы.Filter(32+128,"*");
   Если Темы.Count=0 Тогда
       Возврат;
   КонецЕсли;
   Файлы=Это.Новый(Это.Enumerator,Темы);
   Пока Файлы.atEnd(0)=0 Цикл
       РекурсивноПапки(Файлы.item(0).Path,Сп);
       Файлы.moveNext(0);
   КонецЦикла;
КонецПроцедуры


Процедура Сформировать()
   Перем Сп;
   РекурсивноПапки(КаталогИБ(),Сп);
   Сп.ВыбратьЗначение("");
КонецПроцедуры    // Сформировать
28 Vladal
 
30.01.12
13:08
(27) Еще не рыл туда. Наверно, так. Спасибо.
Сейчас приоритет задачи сменили, проверить пока не смогу, но на заметочку взял.
29 Vladal
 
30.01.12
14:02
Нашел еще один скрипт, который просматривает указанную папку и создаёт лог с именами файлов

'**********************************************
'* GetListFiles.vbs
'*---------------------------------------------
'* Скрипт получения списка файлов
'*---------------------------------------------
'* Programming by VerSys, 2008
'**********************************************
Option Explicit
'
'Переменные и константы
Public strPath      'Патч текущих диска, папки, подпапки
Public strSeparator 'Строка-разделитель списка
Public strSpace     'Строка с заданным количеством пробелов
Public strBuffer    'Строка-накопитель сведений о папках, файлах
Dim strFileName     'Имя файла отчета
Const strHead = "Выберите диск или папку:"
'
'объектные переменные
 Dim objShell
 Dim objDialogFolder    
 Dim objDialogFolderItem
 Dim objFolder
 Dim objFolderItem
 Dim objFSO
'инициализация переменных
  strSeparator = String(40, "-")
  strSpace = Space(3)
'--------------------------------------------------------------
'Формируем диалоговое окно "Обзор папок"
Set objShell = CreateObject("Shell.Application") 'Объект Shell    
Set objDialogFolder = objShell.Namespace(&H11&)  'Name_Space = "Мой компьютер",
Set objDialogFolderItem = objDialogFolder.Self   'и устанавливаем по умолчанию в диал.окне
    strPath = objDialogFolderItem.Path
'
'Выводим диалоговое окно "Обзор папок"
Set objFolder = objShell.BrowseForFolder(0,strHead,0,strPath)
'
'Если ничего не выбрано - завершаем скрипт      
If objFolder Is Nothing Then
   Wscript.Quit
End If
'
'Если пользователь выбрал диск или папку:
''получаем патч из диалога
 Set objFolderItem = objFolder.Self
     strPath = objFolderItem.Path
'
''создаем File System Object
 Set objFSO = CreateObject("Scripting.FileSystemObject")
'
''проверяем доступность указанного ресурса
If objFSO.FolderExists(strPath) = False Then
   MsgBox "Нет доступа к ресурсу ''" &  strPath & "''",_
          vbOkOnly + vbCritical, strPath
   Wscript.Quit
End If
'
''вызываем функцию прохода по каталогам и файлам
 dhGetListFolderFile(strPath)
'
''Создаем файл отчета
'''Формируем имя файла отчета как строка патча с заменой недопустимых символов
   strFileName = Replace(Replace(strPath, ":\", "-"), "\", "=")
   strFileName = strFileName & ".txt"
'''Результат пишем в файл
   With objFSO.CreateTextFile(strFileName)
    .WriteLine(strBuffer)
    .Close
   End With
'
'Уничтожаем объекты
Set objShell = Nothing
Set objDialogFolder = Nothing
Set objDialogFolderItem = Nothing
Set objFolder = Nothing
Set objFolderItem = Nothing
Set objFSO = Nothing
'
'Сообщаем о создании отчета
MsgBox "Отчет создан в файле:" & Chr(13) &_
       "''" & strFileName & "''", vbOkOnly + vbInformation, strPath
'
'--------------------------------------------------------------
' FUNCTION'S
'--------------------------------------------------------------
Function dhGetListFolderFile(strFolderName)
'Функция прохода по каталогам и файлам
Dim dFolder, dFile, dSubFolder
  'получаем патч каталога
   Set dFolder = objFSO.GetFolder(strFolderName)
   'проходим файлы текущего каталога
       strBuffer = strBuffer & strFolderName & " <DIR>" & vbNewLine
   For Each dFile In dFolder.Files
       strBuffer = strBuffer & strSpace & dFile.Name & " - " & dFile.Size & vbNewLine
   Next
       strBuffer = strBuffer & strSeparator & vbNewLine
   'проходим рекурсивно по всем подкаталогам
   For Each dSubFolder In dFolder.SubFolders
       dhGetListFolderFile(dSubFolder.Path)
   Next
End Function