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

Пишу микро прогу на плюсах которая сортирует файлы по папкам и возникает проблема. После хоть 1 выполнения функции sort_files(std::string file) у меня в выводе терминала зацикленно появляется mv: cannot stat путь к файлу No such file or directory с чем это связано мне не ясно. Судя по всему проблема в функции check_files(). Если я задаю переменную std::string file глобальной(до функций) то в терминале ничего не появляется но при этом программа работает только 1 раз а не постоянно. (Все переменные написанные капсом это абсолютные пути к папкам, файлам либо команды терминалу перейти в папку)

void sort_file(std::string file)

    {
        if (file == ".pdf")
            system(MOVE_BOOKS);
    }

void check_files()

    {
        for (unsigned i = 0; i < files.size(); ++i)
            for (unsigned j = 0; j < files[i].size(); ++j)
                if(files[i][j] == '.')
                {
                    std::string file;
                    for (unsigned l = j; l < files[i].size(); ++l)
                        file += files[i][l];
    
                    sort_file(file);
                    break;
                }
    }

void run()
{

    std::string line;

    
    system("ls " BASE "> .tmp");

    std::ifstream tmp(".tmp");

    if (tmp.is_open())
        while(getline(tmp, line))
            files.push_back(line);
    
    tmp.close();


    check_files();
    

    std::this_thread::sleep_for(std::chrono::seconds(1));
}



int main(int argc, char* argv[])
{

    make_base_catalogs();   
    while(true)
    {
        run();

    }

    return 0;
}

Ответы (1 шт):

Автор решения: DmitryK

Без полного текста тяжело сказать что-то конкретно. Но пара замечаний есть - может поможет как-то.

  1. Вектор строк files заполняется, но нигде не очищается. Вы добавляете в массив строк имена файлов из текущей директории. Либо вы работаете со всё время увеличивающимся массивом, в котором вероятно есть дубликаты. Либо возможно очищаете где-то в другом месте? Или не очищаете... И так делаете 1 раз в секунду. И тут может быть ошибка - в списке есть расширение .pdf, а файлов с таким расширением в папке нет. Вероятно поэтому у вас идет циклически No such file or directory, когда вызывается системная функция для перемещения файлов, которых в папке нет. Поэтому перед каждым заполнением массив files нужно очищать от старых значений.
void run()
{
    std::string line;
    // по идее вот здесь надо очистить массив files   <-------------
    // files.clear();                                 <-------------
    system("ls " BASE "> .tmp"); // записали список файлов в файл
    std::ifstream tmp(".tmp");
    if (tmp.is_open())
        while(getline(tmp, line))
            files.push_back(line); // добавили имена файлов в массив
    tmp.close();
    check_files();
    std::this_thread::sleep_for(std::chrono::seconds(1));
}

Я так понимаю, вам этот список нужен только 1 раз, для проверки есть ли в папке определенные файлы.
Также происходит, если вы делаете глобальной переменную std::string file. Вы её не очищаете, и в ней появляется значение .pdf.pdf.pdf.pdf. А как раз с локальной переменной функция check_files() работает корректно, правда неоптимально.
2. Перебирая имена файлов в массиве files вы пытаетесь получить расширение файла. Но ищете первую точку в имени. А в имени файла может быть несколько точек. Вероятно нужно искать последнее вхождение точки в имя. Ну и проще делать это через функции поиска в строках.

void check_files()
{
    for (unsigned i = 0; i < files.size(); ++i)
    {
        std::string::size_type n;
        n = files[i].rfind('.');
        if( n!= std::string::npos )
            sort_file( files[i].substr(n) );
    }
}    
  1. Поскольку вам нужны расширения, лучше сразу при чтении строки из файла выделять расширение и записывать в files только его - место сэкономите. И скорость работы повысится, т.к. расширение влезает в "короткую" строку и std::string не выделяет память в куче. А если строка будет с путем (или имя файла длинное), то полное имя может и не влезть - тогда string выделит память в куче, куда запишет строку.
  2. Файлов с одинаковым расширением в папке может быть несколько. Вы несколько раз будете вызывать sort_file(file) для одного и того же расширения. А если расширение ".pdf", то несколько раз вызовете системную функцию system(MOVE_BOOKS);, хотя файлов там уже нет (после первого вызова вы их переместите). Т.е. вам нужен список расширений файлов без повторов. Для этого вместо std::vector<> проще использовать std::set<> или std::unordered_set<>. И если вы реагируете только на 1 расширение, искать именно его поиском во множестве вместо перебора вектора в цикле. Да и sort_file() можно сразу вызывать.
std::set< std::string > files;
void run()
{
   ...
    files.clear();
    if (tmp.is_open())
        while(getline(tmp, line))
        {
            std::string::size_type n;
            n = line.rfind('.');
            if( n!= std::string::npos )
                files.insert(line.substr(n)); // добавили сразу расширение файлов в массив
        }
    auto search = files.find(".pdf");
    if (search != files.end())
        sort_file(*search);
   ...
}

Можно оптимизировать ещё сильнее - добавляете во множество расширения не всех файлов из списка, а только тех, с которыми будете дальше работать (".pdf"). А если оно одно такое - то вообще не делаете список, а сразу вызываете sort_file();

→ Ссылка