3

I would like to use std::filesystem in my project, which will allow me to show .txt files in the current directory (I use Ubuntu, I don't need a Windows function because I have already seen one on StackOverflow).

Here is my GitHub repo:

https://github.com/jaroslawroszyk/-how-many-pages-per-day

I have a fix for this problem like this:

void showFilesTxt()
{
    DIR *d;
    char *p1, *p2;
    int ret;
    struct dirent *dir;
    d = opendir(".");
    if (d)
    {
        while ((dir = readdir(d)) != NULL)
        {
            p1 = strtok(dir->d_name, ".");
            p2 = strtok(NULL, ".");
            if (p2 != NULL)
            {
                ret = strcmp(p2, "txt");
                if (ret == 0)
                {
                    std::cout << p1 << "\n";
                }
            }
        }
        closedir(d);
    }
}

But the code I enter here would like to use C++17, but I don't know how to find the .txt files, now I wrote:

for (auto &fn : std::filesystem::directory_iterator("."))
    if (std::filesystem::is_regular_file(fn))
    {
        std::cout << fn.path() << '\n';
    }
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Eriss69
  • 69
  • 5

2 Answers2

5

If you look into the reference (https://en.cppreference.com/w/cpp/filesystem/path) you will find the extension() method on paths (https://en.cppreference.com/w/cpp/filesystem/path/extension) which returns you the file's extension. Now you simply need to use the string() function on the path's extension and compare the string.

Something like

for (auto& p : std::filesystem::directory_iterator(".")) {
    if (p.is_regular_file()) {
        if (p.path().extension().string() == ".txt") {
            std::cout << p << std::endl;
        }
    }
}
hefe
  • 193
  • 8
  • 3
    Note that a `directory_iterator` dereferences to a `directory_entry`, not a `path`, so you would need to use `p.path().extension()` instead of `p.extension()`. Also, you can use `p.is_regular_file()` instead of `std::filesystem::is_regular_file(p.path())`. And, you can use `string() == ".txt"` instead of `string().compare(".txt") == 0`. – Remy Lebeau Jul 06 '21 at 23:25
2

In C++20, you can just check if the path().string() ends with .txt by using the std::string::ends_with member function:

#include <filesystem>
#include <iostream>

int main() {
    for(auto& de : std::filesystem::directory_iterator(".")) {
        if(de.is_regular_file() && de.path().string().ends_with(".txt")) {
            std::cout << de << '\n';     // or `de.path().string()
        }
    }
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • how to remove "./" at the beginning and the extension so that it was not visible in the program operation – Eriss69 Jul 06 '21 at 20:39
  • 1
    @JarosławRoszyk If the files are all in the same directory, you can do `std::cout << de.path().filename()` to only get the filename part of the path. If you later decide to do a recursive search, only printing the filename may be confusing though. – Ted Lyngmo Jul 06 '21 at 20:42
  • Thank you so much, you can use c++ 20 but I haven't studied it yet, I stopped at c ++ 11/14 – Eriss69 Jul 06 '21 at 20:46
  • @JarosławRoszyk You're welcome! Glad it helped! You have many helper functions if you look at [`std::filesystem::path`](https://en.cppreference.com/w/cpp/filesystem/path) that you can use to do fun stuff with. The `path` has iterators so you can loop over the individual components (directories) in the path too. – Ted Lyngmo Jul 06 '21 at 20:53
  • I know, but I have to understand how to read c reference because sometimes I go dumb – Eriss69 Jul 06 '21 at 20:56
  • 1
    @JarosławRoszyk It took me a while to get used to cppreference too, but now it's my best friend :-) – Ted Lyngmo Jul 06 '21 at 20:58
  • 1
    I need to meet this friend haha – Eriss69 Jul 07 '21 at 22:18