Поиск и удаление в субдиректориях

Тема в разделе "WASM.BEGINNERS", создана пользователем vg, 10 июн 2007.

  1. vg

    vg New Member

    Публикаций:
    0
    Регистрация:
    16 апр 2007
    Сообщения:
    475
    Есть функция, которая находит и удаляет все файлы в указанной директории

    Код (Text):
    1. pathanymask              db "\*",0
    2.  
    3. LOCAL WFD:WIN32_FIND_DATA
    4. invoke SetCurrentDirectory,ADDR fullpathfordelete
    5. invoke lstrcat,addr fullpathfordelete,addr pathanymask
    6. invoke FindFirstFile,addr fullpathfordelete,addr WFD
    7. cmp eax,INVALID_HANDLE_VALUE
    8. je exit
    9. mov hFind,eax
    10. deleting:
    11. invoke FindNextFile,hFind,addr WFD
    12. test eax,eax
    13. jz exit
    14. invoke DeleteFile,addr WFD.cFileName
    15. jmp deleting
    16. exit:
    17. invoke FindClose,hFind
    Как находить и удалять файлы во вложенных папках?
    Насколько я понимаю, после нахождения очередного элемента каталога проверяем установлен ли бит FILE_ATTRIBUTE_DIRECTORY в поле WFD.dwFileAttributes, если установлен, то начинаю проверять этот элемент, дальше... захожу в тупик.
    Может у кого есть подходящий "кусочек" кода (masm32)? SHFileOperation не подходит.
     
  2. RamMerLabs

    RamMerLabs Well-Known Member

    Публикаций:
    0
    Регистрация:
    11 сен 2006
    Сообщения:
    1.426
    надоело уже писать, что google.ru работает превосходно!
     
  3. maxdiver

    maxdiver Max

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    308
    Адрес:
    Саратов
    vg
    Сделай функцию, которая удаляет все файлы в указанном ей каталоге, а потом рекусивно вызывает себя из каждого подкаталога.
     
  4. vg

    vg New Member

    Публикаций:
    0
    Регистрация:
    16 апр 2007
    Сообщения:
    475
    maxdiver
    Можно про это по подробнее?
     
  5. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    рекурсивная функция - функция, которая вызывает сама себя.
     
  6. vg

    vg New Member

    Публикаций:
    0
    Регистрация:
    16 апр 2007
    Сообщения:
    475
    Может у кого-нибудь есть пример?
     
  7. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    у гугла точно есть.
     
  8. maxdiver

    maxdiver Max

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    308
    Адрес:
    Саратов
    Ну вот например (написано очень давно, поэтому за стиль не пинать ;) ):
    Код (Text):
    1. .data
    2.  
    3. ThisDirectory   db ".",0
    4. SearchMask      db "\*",0
    5. Slash               db "\",0
    6.  
    7.  
    8. .code
    9.  
    10.  
    11. scan_directory PROC Directory:PBYTE
    12.  
    13. LOCAL FindData:WIN32_FIND_DATA, SearchFilter[MAX_PATH]:byte, CurFileName[MAX_PATH]:byte
    14. LOCAL hFind:HANDLE
    15.  
    16. ; получаем фильтр для поиска
    17.  
    18. push Directory
    19. lea ebx, SearchFilter
    20. push ebx
    21. call lstrcpy
    22.  
    23. lea ebx, SearchMask
    24. push ebx
    25. lea ebx, SearchFilter
    26. push ebx
    27. call lstrcat
    28.  
    29. ; начинаем поиск
    30.  
    31. lea ebx, FindData
    32. push ebx
    33. lea ebx, SearchFilter
    34. push ebx
    35. call FindFirstFile
    36. mov [hFind], eax
    37.  
    38. inc eax
    39. test eax, eax
    40. jz scan__finish
    41.  
    42. scan__find_next_file:
    43.  
    44.     ; что-то нашли
    45.  
    46.     mov eax, [FindData.dwFileAttributes]
    47.     and eax, FILE_ATTRIBUTE_DIRECTORY
    48.     test eax, eax
    49.     jnz scan__its_directory
    50.  
    51.     jmp scan__its_file 
    52.     scan__its_directory:
    53.  
    54.         ; если нашли папку
    55.  
    56.         ; проверяем, что это не . или ..
    57.         lea esi, FindData.cFileName
    58.         lodsb
    59.         cmp al, '.'
    60.         jne scan__its_real_dir
    61.         lodsb
    62.         test al, al
    63.         je scan__continue
    64.         cmp al, '.'
    65.         jne scan__its_real_dir
    66.         lodsb
    67.         test al, al
    68.         je scan__continue
    69.        
    70.         scan__its_real_dir:
    71.            
    72.             ; рекурсивно заходим в найденную папку
    73.  
    74.             push [Directory]
    75.             lea ebx, CurFileName
    76.             push ebx
    77.             call lstrcpy
    78.  
    79.             lea ebx, Slash
    80.             push ebx
    81.             lea ebx, CurFileName
    82.             push ebx
    83.             call lstrcat
    84.  
    85.             lea ebx, [FindData.cFileName]
    86.             push ebx
    87.             lea ebx, CurFileName
    88.             push ebx
    89.             call lstrcat
    90.  
    91.             lea ebx, CurFileName
    92.             push ebx
    93.             call scan_directory
    94.    
    95.         jmp scan__continue
    96.    
    97.     scan__its_file:
    98.    
    99.         ; если нашли файл
    100.         ; что-нибудь с ним делаем
    101.  
    102.     scan__continue:
    103.     ; переходим к следующему файлу
    104.     lea ebx, FindData
    105.     push ebx
    106.     push [hFind]   
    107.     call FindNextFile
    108.     test eax, eax
    109.     jnz scan__find_next_file
    110.  
    111. ; конец
    112. push [hFind]
    113. call FindClose
    114.  
    115. scan__finish:
    116. ret
    117.  
    118. scan_directory ENDP
    119.  
    120.  
    121.  
    122. start:
    123.  
    124. lea ebx, ThisDirectory
    125. push ebx
    126. call scan_directory
    127.  
    128. ...
    129.  
    130. end start
     
  9. vg

    vg New Member

    Публикаций:
    0
    Регистрация:
    16 апр 2007
    Сообщения:
    475
    Пытаюсь переделать свою функцию в рекурсивную

    Код (Text):
    1. updirmask              db "..",0
    2. slash                  db "\",0
    3. pathanymask            db "\*",0
    4.  
    5. FindandDelete proc
    6.  
    7. LOCAL WFD:WIN32_FIND_DATA
    8.  
    9. invoke lstrcpy,addr curentdirectory,ADDR fullpathfordelete
    10.  
    11. invoke SetCurrentDirectory,ADDR fullpathfordelete
    12. invoke lstrcat,addr fullpathfordelete,addr pathanymask
    13. invoke FindFirstFile,addr fullpathfordelete,addr WFD
    14. cmp eax,INVALID_HANDLE_VALUE
    15. je exit1
    16. mov hFind,eax
    17. deleting:
    18. invoke FindNextFile,hFind,addr WFD
    19. test eax,eax
    20. jz exit1
    21. cmp WFD.dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY
    22. jne @F
    23. invoke lstrcmp,addr WFD.cFileName,addr updirmask
    24. cmp eax,0
    25. je @F
    26. invoke lstrcpy,addr curentdirectory1,ADDR curentdirectory
    27. invoke lstrcat,addr curentdirectory1,addr slash
    28. invoke lstrcat,addr curentdirectory1,addr WFD.cFileName
    29. invoke lstrcpy,addr fullpathfordelete,ADDR curentdirectory1
    30. invoke FindandDelete
    31. @@:
    32. invoke DeleteFile,addr WFD.cFileName
    33. jmp deleting
    34. exit1:
    35. invoke FindClose,hFind
    36.  
    37. ret
    38. FindandDelete endp
    Прога вылетает.
    Где ошибка? Как сделать правильно?
     
  10. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    0) атрибуты объекта - это маска, поэтому проверять надо через AND/TEST.
    1) кроме ".." есть ещё и "."
    2) использовать глобальные переменные в рекурсии не кузяво.
    3) поищи по форуму, уж чего-чего, а примеров рекурсивного поиска и удаления файлов валом.
     
  11. vg

    vg New Member

    Публикаций:
    0
    Регистрация:
    16 апр 2007
    Сообщения:
    475
    Так тоже работает.

    Согласен. Поэтому
    invoke FindFirstFile,firstdirectory,addr WFD
    cmp eax,INVALID_HANDLE_VALUE
    je exit1
    mov hFind,eax
    deleting:
    invoke FindNextFile,hFind,addr WFD

    Больше не буду.

    Раньше искал. Ничего подходящего не нашёл.


    Учёл все советы.

    Код (Text):
    1. FindandDelete proc firstdirectory:DWORD
    2. LOCAL curentdirectory[MAX_PATH]  :byte
    3. LOCAL curentdirectory1[MAX_PATH] :byte
    4. LOCAL WFD                        :WIN32_FIND_DATA
    5.  
    6. invoke lstrcpy,addr curentdirectory,firstdirectory
    7.  
    8. invoke SetCurrentDirectory,firstdirectory
    9. invoke lstrcat,firstdirectory,addr pathanymask
    10. invoke FindFirstFile,firstdirectory,addr WFD
    11. cmp eax,INVALID_HANDLE_VALUE
    12. je exit1
    13. mov hFind,eax
    14. deleting:
    15. invoke FindNextFile,hFind,addr WFD
    16. test eax,eax
    17. jz exit1
    18. cmp WFD.dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY
    19. jne @F
    20. invoke lstrcmp,addr WFD.cFileName,addr updirmask
    21. cmp eax,0
    22. je @F
    23. invoke lstrcpy,addr curentdirectory1,ADDR curentdirectory
    24. invoke lstrcat,addr curentdirectory1,addr slash
    25. invoke lstrcat,addr curentdirectory1,addr WFD.cFileName
    26. invoke lstrcpy,addr fullpathfordelete,ADDR curentdirectory1
    27. invoke FindandDelete,ADDR fullpathfordelete
    28. @@:
    29. invoke DeleteFile,addr WFD.cFileName
    30. jmp deleting
    31. exit1:
    32. invoke FindClose,hFind
    33.  
    34. ret
    35. FindandDelete endp
    Кажется, теперь похоже на правду, но прога всё равно вылетает.
    Может кто-нибудь видит ошибку?
     
  12. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Говоришь, работает?
     
  13. vg

    vg New Member

    Публикаций:
    0
    Регистрация:
    16 апр 2007
    Сообщения:
    475
    IceStudent
    Работает в этом месте, т. е. определяет папку.
    Вылетает дальше.
     
  14. vg

    vg New Member

    Публикаций:
    0
    Регистрация:
    16 апр 2007
    Сообщения:
    475
    Переделал по примеру maxdiver
    Код (Text):
    1. updirmask              db "..",0
    2. slash                  db "\",0
    3. pathanymask            db "\*",0
    4.  
    5.  
    6. FindandDelete proc Directory :DWORD
    7. LOCAL SearchFilter[MAX_PATH] :byte
    8. LOCAL CurFileName[MAX_PATH]  :byte
    9. LOCAL WFD                    :WIN32_FIND_DATA
    10.  
    11. invoke SetCurrentDirectory,Directory
    12. invoke lstrcpy,addr SearchFilter,Directory
    13. invoke lstrcat,addr SearchFilter,addr pathanymask
    14. invoke FindFirstFile,addr SearchFilter,addr WFD
    15. cmp eax,INVALID_HANDLE_VALUE
    16. je exit1
    17. mov hFind,eax
    18. deleting:
    19. invoke FindNextFile,hFind,addr WFD
    20. test eax,eax
    21. jz exit1
    22. cmp WFD.dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY
    23. jne @F
    24. invoke lstrcmp,addr WFD.cFileName,addr updirmask
    25. cmp eax,0
    26. je deleting
    27. invoke lstrcpy,addr CurFileName,Directory
    28. invoke lstrcat,addr CurFileName,addr slash
    29. invoke lstrcat,addr CurFileName,addr WFD.cFileName
    30. invoke FindandDelete,addr CurFileName
    31. jmp deleting
    32. @@:
    33. invoke DeleteFile,addr WFD.cFileName
    34. jmp deleting
    35. exit1:
    36. invoke FindClose,hFindret
    37. FindandDelete endp
    Всё равно не работает.

    Может теперь кто-нибудь увидит ошибку?
     
  15. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    vg
    поставь себе отладчик.
     
  16. Mental_Mirror

    Mental_Mirror New Member

    Публикаций:
    0
    Регистрация:
    7 май 2007
    Сообщения:
    431
    Вот оптимизированный вариант функции с исправленной ошибкой. Ошибка была в том что hFind - была глобальной переменной со всеми отсюда последствиями.
    Код (Text):
    1. FindandDelete proc Directory :DWORD
    2.     LOCAL SearchFilter[MAX_PATH]      :BYTE
    3.     LOCAL CurFileName[MAX_PATH]      :BYTE
    4.     LOCAL WFD                                 :WIN32_FIND_DATA
    5.            LOCAL hFind                                :DWORD
    6.  
    7.     invoke      SetCurrentDirectory,Directory
    8.     invoke      lstrcpy,addr SearchFilter,Directory
    9.     invoke      lstrcat,addr SearchFilter,addr pathanymask
    10.     invoke      FindFirstFile,addr SearchFilter,addr WFD
    11.     inc          eax
    12.     je           exit2
    13.     dec         eax
    14.     mov        hFind,eax
    15. deleting:
    16.     invoke     FindNextFile,hFind,addr WFD
    17.     xchg       eax,ecx
    18.     jecxz      exit1
    19.     cmp        WFD.dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY
    20.     jne         @F
    21.     invoke     lstrcmp,addr WFD.cFileName,addr updirmask
    22.     xchg       eax,ecx
    23.     jecxz      deleting
    24.     invoke     lstrcpy,addr CurFileName,Directory
    25.     invoke     lstrcat,addr CurFileName,addr slash
    26.     invoke     lstrcat,addr CurFileName,addr WFD.cFileName
    27.     invoke     FindandDelete,addr CurFileName
    28.     jmp         deleting
    29. @@:
    30.     invoke     DeleteFile,addr WFD.cFileName
    31.     jmp         deleting
    32. exit1:
    33.     invoke     FindClose,hFind
    34. exit2:
    35.            ret
    36. FindandDelete endp
     
  17. vg

    vg New Member

    Публикаций:
    0
    Регистрация:
    16 апр 2007
    Сообщения:
    475
    Большое спасибо.
     
  18. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Второй раз говорю, не будет оно работать толком. Каталоги могут иметь кучу атрибутов помимо атрибута "каталог".

    Кстати, странно, что при задании маски "*.*" находятся и директории - ведь их имена не содержат точку. Разве что "file." == "file".
     
  19. shoo

    shoo New Member

    Публикаций:
    0
    Регистрация:
    17 июл 2003
    Сообщения:
    1.537
    Адрес:
    Ukraine
    так и есть. кстати, по-моему "file." - способ явно указать что у файла пустое расширение (а не расширение по умолчанию) - это имеет смысл в диалогах открытия/сохранения файлов, где имеется расширение по умолчанию. а также в каких-то случаях система автоматически добавляет к "file" без точки расширение "ехе" - но точно не помню когда.
     
  20. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    В шелле - подставляет расширения из PATHEXT.