List Files in a Directory
Learn to display the list files in a directory.
We'll cover the following...
The filesystem
library provides a directory_entry
class with directory-related information about a given path
. We can use this to create useful directory listings.
How to do it
In this recipe, we create a directory_entry
class:
• We start with our namespace alias and formatter
specialization for displaying path
objects:
namespace fs = std::filesystem;template<>struct std::formatter<fs::path>:std::formatter<std::string> {template<typename FormatContext>auto format(const fs::path& p, FormatContext& ctx) {return format_to(ctx.out(), "{}", p.string());}};
The
directory_iterator
class makes it easy to list a directory:
int main() {constexpr const char* fn{ "." };const fs::path fp{fn};for(const auto& de : fs::directory_iterator{fp}) {cout << format("{} ", de.path().filename());}cout << '\n';}
Output:
chrono Makefile include chrono.cpp working formattertestdir formatter.cpp working.cpp
We can add command-line options to make this work, like Unix
ls
:
int main(const int argc, const char** argv) {fs::path fp{ argc > 1 ? argv[1] : "." };if(!fs::exists(fp)) {const auto cmdname {fs::path{argv[0]}.filename() };cout << format("{}: {} does not exist\n", cmdname, fp);return 1;}if(is_directory(fp)) {for(const auto& de : fs::directory_iterator{fp}) {cout << format("{} ", de.path().filename());}} else {cout << format("{} ", fp.filename());}cout << '\n';}
If there is a command-line argument, we use it to create a path
object. Otherwise, we use ".
" for the current directory.
We check if the path exists with if_exists()
. If not, we print an error message and exit. The error message includes cmdname
from argv[0]
.
Next, we check is_directory()
. If we have a directory, we loop through a directory_iterator
for each entry. directory_iterator
iterates over directory_entry
objects. de.path().filename()
gets the path and filename from each directory_entry
object.
Output:
./workingchrono Makefile include chrono.cpp working formattertestdir formatter.cpp working.cpp./working working.cppworking.cpp./working foo.barworking: foo.bar does not exist
If we want our output sorted, we can store our
directory_entry
objects in a sortable container.
Let's create an alias for fs::directory_entry
. We'll be using this a lot. This goes at the top of the file:
using de = fs::directory_entry;
At the top of main()
, we declare a vector
of de
objects:
vector<de> entries{};
Inside the is_directory()
block, we load the vector
, sort it, and then ...