Gistrec icon

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

Gistrec | PRO | 06/03/18 09:41:42 AM UTC | 0 ⭐ | 834 👁️ | Never ⏰ | []
C++ |

6.4 KB

|

None

|

0 👍

/

0 👎

/**
 * find.exe <directory> -name "file.*"
 * -abc сортирует по возрастанию, -cba по убывания
 * Пример find.exe C:\test\ -name "*.txt" -abc
 * Что выведет:
 *    C:\test\folder2\doc.txt
 *    C:\test\folder2\doc1.txt
 *    C:\test\folder3\folder2\doc1.txt
 */
 
#include <iostream> // Для cin, cout, endl
#include <string> // для string
#include <vector> // для vector
#include <windows.h> // для поиска файлов - WIN32_FIND_DATA, HANDLE, FindFirstFile, ...
#include <algorithm> // Для сортировки sort()
 
using namespace std;
 
// Структура данных о файле. 
// Содержит название, аттрибуты, и прочее
WIN32_FIND_DATA fileData; 
HANDLE handle; // Поисковой дискриптор. Нужен для функции FindFirstFile
 
// Функция нужна для поиска папок в заданной папке
// Например На диске C:\ есть папки dir1 и dir2
// Тогда вызвав findSubdirectory("C:\") получим вектор с "dir1" и "dir2"
vector<string> findSubdirectory(string &dir) {
    vector<string> subdirectories; // Массив с названием папок
 
    // Создаем поисковой дискриптор
    handle = FindFirstFile(dir.c_str(), &fileData);
 
    // INVALID_HANDLE_VALUE возникает когда не найден путь/директория
    if (handle != INVALID_HANDLE_VALUE) {
        // Выполняем цикл, пока существуют файлы
        do {
            // Если найденная сущность является папкой, добавляем название в массив папок
            if ((fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
                subdirectories.push_back(fileData.cFileName);
            }
        } while (FindNextFile(handle, &fileData) != 0);
    }
    FindClose(handle);
    return subdirectories;
}
 
// Функция нужна для поиска файлов.
// На вход подается строка, директория + название файла. Поддерживает маску.
// Например C:\test.* или C:\* или C:\test\dir\file.doc
// Возвращаемое значение - вектор с названиями файлов (без директории)
vector<string> findFiles(string &filePatch) {
    vector<string> result;
 
    handle = FindFirstFile(filePatch.c_str(), &fileData);
 
    if (handle != INVALID_HANDLE_VALUE) {
        do {
            //если найденный файл не является папкой добавляем его в вектор
            if ((fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
                result.push_back(fileData.cFileName);
            }
        } while (FindNextFile(handle, &fileData) != 0);     
        FindClose(handle);
    }
    return result;
}
 
// Поиск файла
// 1. Ищем файл в текущей директории
// 2. Ищем все субдиректории
// 3. Для каждой субдиректории выполняем эту же функцию
//
// Если нам нужно сортировать результат, то сначала мы должны создать 
// vector<string> из найденных файлов, а потом отсортировать их
// А если нам не нужно сортировать - то мы можем сразу выводить найденные файлы
//
// dir - директория, например C:\ или C:\Users\Alex
// fileName - название файла, myFile.cpp или *file.*
// result - результат. Сюда будем записывать найденные файлы.
void find(vector<string> &result, string &dir, string &fileName, bool needSave) {
    // 1. Ищем файлы в текущей директории
    vector<string> files = findFiles(dir + fileName);
    // Если не нужно сохранять, то выводим найденные файлы
    if (!needSave) {
        for (auto findFileName : files) {
            cout << dir << findFileName << endl;
        }
    // Если нужно сохранять, то добавляем найденные файлы в result
    } else {
        for (auto fileName : files) {
            result.push_back(dir + fileName);
        }
    }
    // 2. Ищем все папки в текущей директории
    vector<string> dirs = findSubdirectory(dir + "*");
    
    // 3. Для всех найденных папок выполням эту же функцию
    // Указатели на текущую директорию "." и на директорию выше ".." не учитываем
    for (auto find_dir : dirs) {
        if (find_dir != "." && find_dir != "..") {
            // cout << "Выплняем поиск в папке " << (dir + find_dir) << endl;
            find(result, dir + find_dir + "\\", fileName, needSave);
        }
    }
}
 
// argc - кол-во аргументов, переданное программе
// argv - сами аргументы
int main(int argc, char* argv[]) {
    setlocale(LC_ALL, "Russian");
    string directory;
    string fileName;
    int sort = 0; // "1" - abc, "-1" - cba, "0" - нет сортировки
    // Для всех аргументов
    for (int i = 0; i < argc; ++i) {
        string arg = argv[i];
        // Первым аргументом задаётся директория
        if (i == 1) directory = arg;
        else if (arg == "-abc") sort = 1;
        else if (arg == "-cba") sort = -1;
        else if (arg == "-name") {
            fileName = argv[i + 1];
            i++;
        }
    }
 
    // Если не задана директория или название файла - выходим из программы
    if (directory.size() == 0 || fileName.size() == 0) {
        cout << "Используйте find.exe <directory> -name <fileName> [-abc/-cab]" << endl;
        return 0;
    }
 
    vector<string> result;
    
    // Вызываем функцию для рекурсивного поиска файлов
    find(result, directory, fileName, (sort != 0));
 
    if (sort != 0) {
        // Сортируем от A до Z
        std::sort(result.begin(), result.end());
        // Если нужно соритровать в обратном порядке, реверсим массив
        if (sort == -1) std::reverse(result.begin(), result.end());
 
        for (auto fileName : result) {
            cout << fileName << endl;
        }
    }
 
    return 0;
}

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎