Библиотека обхода каталога и подкаталогов

Ответить
ya
^-^
Сообщения: 2336
Зарегистрирован: 16 дек 2021, 19:56

Библиотека обхода каталога и подкаталогов

Сообщение ya »

Программа обходит файлы заданного расширения в каталоге и подкаталоге и совершает над ними действия

folder_read.cpp

Код: Выделить всё

//g++ -std=c++11 -o folder_read folder_read.cpp
/*

            Программа обходит файлы заданного расширения в каталоге и подкаталоге и совершает над ними действия
 
*/
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <dirent.h>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <string>
#include <cmath>
#include <filesystem>
#include <fstream>
#include <iterator>
#include <stdexcept>
#include <unordered_map>
#include <utility>
#include <array> 
#include <sstream>
#include <algorithm>
#include <sys/stat.h>

#ifdef _WIN32
    #include <windows.h>
#else
    #include <unistd.h>
#endif

class IFolderRead
{
public:
    virtual void setStartDirectory(const std::string& start_directory) = 0;
    virtual void runSystem() = 0;
    virtual void setSystem(const std::string& command) = 0;
    virtual void setValidExtensions(const std::vector<std::string>& valid_extensions) = 0;
    virtual void setOutputPathExt(const std::string& output_path_ext) = 0;
};

class FolderRead : public IFolderRead
{

protected:
std::string output_path_ext = ".txt";
std::string start_directory = ".";  // Задайте стартовый каталог (или измените на нужный)
std::string command = "";    
//std::vector<std::string> valid_extensions = {".wmv", ".avi", ".asf", ".flv", ".mkv", ".m4v", ".VOB"};
std::vector<std::string> valid_extensions = {".wmv", ".avi", ".asf", ".flv", ".mkv", ".m4v", ".VOB"};

private:
    
const std::string const_output_path = "[output_path]"; 
const std::string const_input_path = "[input_path]";

std::string stringReplace(const std::string& path, const std::string& find_str, const std::string& replace_str)
{
    // Find and replace
    std::string modified_path = path; // Создадим изменённый путь, чтобы не менять оригинальный
    size_t pos = 0;
    while ((pos = modified_path.find(find_str, pos)) != std::string::npos) {
        modified_path.replace(pos, find_str.length(), replace_str); // Заменяет правильно по длине find_str
        pos += replace_str.length(); // Сдвинем позицию для дальнейших замен
    }
    
    return modified_path;
}


std::string slash_replace(const std::string& input_path)
{
	std::string path = input_path;
    std::cout << "Original path: " << path << std::endl;
    
    // Find and replace all slashes with backslashes
    size_t pos = 0;
    while ((pos = path.find('/', pos)) != std::string::npos) {
        path.replace(pos, 1, "\\");
        pos += 1;
    }
    
    std::cout << "Updated path: " << path << std::endl;
    
    return path;
}


bool is_directory(const std::string& directory_path, dirent* entry)
{
#ifdef _DIRENT_HAVE_D_TYPE
    return entry->d_type == DT_DIR;
#else
    struct stat path_stat;
    std::string full_path = directory_path + "/" + entry->d_name;
    if (stat(full_path.c_str(), &path_stat) == 0)
    {
        return S_ISDIR(path_stat.st_mode);
    }
    else
    {
        return false;
    }
#endif
}


void traverse_directory(const std::string& directory_path)
{
    DIR* dir;
    dirent* entry;

    if ((dir = opendir(directory_path.c_str())) != nullptr)
    {
        while ((entry = readdir(dir)) != nullptr)
        {
            if (this->is_directory(directory_path, entry))
            {
                std::string sub_directory = entry->d_name;

                if (sub_directory != "." && sub_directory != "..")
                {
                    this->traverse_directory(directory_path + "/" + sub_directory);
                }
            }
            else
            {
                const std::string entry_name = entry->d_name;
                const auto ext_start = entry_name.find_last_of('.');

                if (ext_start != std::string::npos)
                {
                    const std::string ext = entry_name.substr(ext_start);

                    if (std::find(this->valid_extensions.begin(), this->valid_extensions.end(), std::string(ext)) != this->valid_extensions.end())
                    {
                        std::string file_path = directory_path + "/" + entry_name;

                        std::cout << "Обрабатываемый файл: " << file_path << std::endl;
                        //set_input_file(file_path);
                        //convert_video(file_path);
                        this->executeSystem(file_path);
                    }
                }
            }
        }
        closedir(dir);
    }
}


void executeSystem(const std::string& input_path)
{
    const auto last_dot_index = input_path.find_last_of('.');
    std::string output_path = input_path.substr(0, last_dot_index) + this->output_path_ext;
    
    std::string command1 = this->stringReplace(this->command, const_input_path, input_path);
    command1 =  this->stringReplace(command1, const_output_path, output_path);
    std::cout << "Выполнение команды: " << command1 << std::endl;
	std::cout << std::endl;
    system(command1.c_str());
}


public:

FolderRead()
{
    setlocale(LC_ALL, "rus");
    //std::string start_directory = ".";  // Задайте стартовый каталог (или измените на нужный)
}

void setStartDirectory(const std::string& start_directory) override
{
    this->start_directory = start_directory;
}

void runSystem() override
{
    this->traverse_directory(start_directory);
}

void setSystem(const std::string& command) override
{
    this->command = command;
}

void setValidExtensions(const std::vector<std::string>& valid_extensions) override
{
    this->valid_extensions = std::move(valid_extensions);
}

void setOutputPathExt(const std::string& output_path_ext)
{
    this->output_path_ext = output_path_ext;
}

};

//Реализация
int main()
{
    // Инициализация конструктора
    IFolderRead* fr  = new FolderRead();
    // Действия над файлами будут выполняться от текущего каталога
    fr->setStartDirectory(".");
    // Устанавливаем расширения для файлов, которые нужно обработать
    fr->setValidExtensions({".sh", ".cpp"});
    // Устанавливаем выходное расширение обработанного файла
    fr->setOutputPathExt(".txt");
    // Команда для выполения, где [input_path] и [output_path] будут заменены входным и выходным файлом 
    fr->setSystem("cat [input_path] > [output_path]");
    // Запуск программы на выполение
    fr->runSystem();
    delete fr;
    return 0;
}
Реализация

Код: Выделить всё

int main()
{
    // Инициализация конструктора
    IFolderRead* fr  = new FolderRead();
    // Действия над файлами будут выполняться от текущего каталога
    fr->setStartDirectory(".");
    // Устанавливаем расширения для файлов, которые нужно обработать
    fr->setValidExtensions({".sh", ".cpp"});
    // Устанавливаем выходное расширение обработанного файла
    fr->setOutputPathExt(".txt");
    // Команда для выполения, где [input_path] и [output_path] будут заменены входным и выходным файлом 
    fr->setSystem("cat [input_path] > [output_path]");
    // Запуск программы на выполение
    fr->runSystem();
    delete fr;
    return 0;
}
Компиляция

Код: Выделить всё

#!/bin/bash
g++ -std=c++11 -o folder_read folder_read.cpp
Ответить