/**
* 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
0 B
|👍
/👎