Advertisement
Gistrec

Поиск файлов по маске

Jun 3rd, 2018
399
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.40 KB | None | 0 0
  1. /**
  2.  * find.exe <directory> -name "file.*"
  3.  * -abc сортирует по возрастанию, -cba по убывания
  4.  * Пример find.exe C:\test\ -name "*.txt" -abc
  5.  * Что выведет:
  6.  *    C:\test\folder2\doc.txt
  7.  *    C:\test\folder2\doc1.txt
  8.  *    C:\test\folder3\folder2\doc1.txt
  9.  */
  10.  
  11. #include <iostream> // Для cin, cout, endl
  12. #include <string> // для string
  13. #include <vector> // для vector
  14. #include <windows.h> // для поиска файлов - WIN32_FIND_DATA, HANDLE, FindFirstFile, ...
  15. #include <algorithm> // Для сортировки sort()
  16.  
  17. using namespace std;
  18.  
  19. // Структура данных о файле.
  20. // Содержит название, аттрибуты, и прочее
  21. WIN32_FIND_DATA fileData;
  22. HANDLE handle; // Поисковой дискриптор. Нужен для функции FindFirstFile
  23.  
  24. // Функция нужна для поиска папок в заданной папке
  25. // Например На диске C:\ есть папки dir1 и dir2
  26. // Тогда вызвав findSubdirectory("C:\") получим вектор с "dir1" и "dir2"
  27. vector<string> findSubdirectory(string &dir) {
  28.     vector<string> subdirectories; // Массив с названием папок
  29.  
  30.     // Создаем поисковой дискриптор
  31.     handle = FindFirstFile(dir.c_str(), &fileData);
  32.  
  33.     // INVALID_HANDLE_VALUE возникает когда не найден путь/директория
  34.     if (handle != INVALID_HANDLE_VALUE) {
  35.         // Выполняем цикл, пока существуют файлы
  36.         do {
  37.             // Если найденная сущность является папкой, добавляем название в массив папок
  38.             if ((fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
  39.                 subdirectories.push_back(fileData.cFileName);
  40.             }
  41.         } while (FindNextFile(handle, &fileData) != 0);
  42.     }
  43.     FindClose(handle);
  44.     return subdirectories;
  45. }
  46.  
  47. // Функция нужна для поиска файлов.
  48. // На вход подается строка, директория + название файла. Поддерживает маску.
  49. // Например C:\test.* или C:\* или C:\test\dir\file.doc
  50. // Возвращаемое значение - вектор с названиями файлов (без директории)
  51. vector<string> findFiles(string &filePatch) {
  52.     vector<string> result;
  53.  
  54.     handle = FindFirstFile(filePatch.c_str(), &fileData);
  55.  
  56.     if (handle != INVALID_HANDLE_VALUE) {
  57.         do {
  58.             //если найденный файл не является папкой добавляем его в вектор
  59.             if ((fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
  60.                 result.push_back(fileData.cFileName);
  61.             }
  62.         } while (FindNextFile(handle, &fileData) != 0);    
  63.         FindClose(handle);
  64.     }
  65.     return result;
  66. }
  67.  
  68. // Поиск файла
  69. // 1. Ищем файл в текущей директории
  70. // 2. Ищем все субдиректории
  71. // 3. Для каждой субдиректории выполняем эту же функцию
  72. //
  73. // Если нам нужно сортировать результат, то сначала мы должны создать
  74. // vector<string> из найденных файлов, а потом отсортировать их
  75. // А если нам не нужно сортировать - то мы можем сразу выводить найденные файлы
  76. //
  77. // dir - директория, например C:\ или C:\Users\Alex
  78. // fileName - название файла, myFile.cpp или *file.*
  79. // result - результат. Сюда будем записывать найденные файлы.
  80. void find(vector<string> &result, string &dir, string &fileName, bool needSave) {
  81.     // 1. Ищем файлы в текущей директории
  82.     vector<string> files = findFiles(dir + fileName);
  83.     // Если не нужно сохранять, то выводим найденные файлы
  84.     if (!needSave) {
  85.         for (auto findFileName : files) {
  86.             cout << dir << findFileName << endl;
  87.         }
  88.     // Если нужно сохранять, то добавляем найденные файлы в result
  89.     } else {
  90.         for (auto fileName : files) {
  91.             result.push_back(dir + fileName);
  92.         }
  93.     }
  94.     // 2. Ищем все папки в текущей директории
  95.     vector<string> dirs = findSubdirectory(dir + "*");
  96.    
  97.     // 3. Для всех найденных папок выполням эту же функцию
  98.     // Указатели на текущую директорию "." и на директорию выше ".." не учитываем
  99.     for (auto find_dir : dirs) {
  100.         if (find_dir != "." && find_dir != "..") {
  101.             // cout << "Выплняем поиск в папке " << (dir + find_dir) << endl;
  102.             find(result, dir + find_dir + "\\", fileName, needSave);
  103.         }
  104.     }
  105. }
  106.  
  107. // argc - кол-во аргументов, переданное программе
  108. // argv - сами аргументы
  109. int main(int argc, char* argv[]) {
  110.     setlocale(LC_ALL, "Russian");
  111.     string directory;
  112.     string fileName;
  113.     int sort = 0; // "1" - abc, "-1" - cba, "0" - нет сортировки
  114.     // Для всех аргументов
  115.     for (int i = 0; i < argc; ++i) {
  116.         string arg = argv[i];
  117.         // Первым аргументом задаётся директория
  118.         if (i == 1) directory = arg;
  119.         else if (arg == "-abc") sort = 1;
  120.         else if (arg == "-cba") sort = -1;
  121.         else if (arg == "-name") {
  122.             fileName = argv[i + 1];
  123.             i++;
  124.         }
  125.     }
  126.  
  127.     // Если не задана директория или название файла - выходим из программы
  128.     if (directory.size() == 0 || fileName.size() == 0) {
  129.         cout << "Используйте find.exe <directory> -name <fileName> [-abc/-cab]" << endl;
  130.         return 0;
  131.     }
  132.  
  133.     vector<string> result;
  134.    
  135.     // Вызываем функцию для рекурсивного поиска файлов
  136.     find(result, directory, fileName, (sort != 0));
  137.  
  138.     if (sort != 0) {
  139.         // Сортируем от A до Z
  140.         std::sort(result.begin(), result.end());
  141.         // Если нужно соритровать в обратном порядке, реверсим массив
  142.         if (sort == -1) std::reverse(result.begin(), result.end());
  143.  
  144.         for (auto fileName : result) {
  145.             cout << fileName << endl;
  146.         }
  147.     }
  148.  
  149.     return 0;
  150. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement