Show Lecture.Filesystem as a slide show.
CS253 Filesystem
Major filesystem classes
<filesystem> defines several classes as part of the nested
namespace std::filesystem
, including:
- The path class represents a single path in a filesystem,
whether relative (
foo
, ./bar
) or absolute (/etc/group
).
- It has several methods to extract parts of the path.
All return a path, except
.native()
, which returns
a string (or a wstring on Windows?).
- A path displays with
"
quotes"
, to protect funny characters.
using namespace filesystem;
path p("/usr/share/dict/linux.words");
cout << "path: " << p << '\n'
<< "native: " << p.native() << '\n'
<< "parent_path: " << p.parent_path() << '\n'
<< "filename: " << p.filename() << '\n'
<< "stem: " << p.stem() << '\n'
<< "extension: " << p.extension() << '\n';
path: "/usr/share/dict/linux.words"
native: /usr/share/dict/linux.words
parent_path: "/usr/share/dict"
filename: "linux.words"
stem: "linux"
extension: ".words"
Many filesystem functions take an optional error_code argument.
If that argument isn’t given, then the function throws a
filesystem_error object if things go bad, which has a nice
error message.
using namespace filesystem;
try {
cout << "/etc/group: " << file_size("/etc/group") << endl;
cout << "doh: " << file_size("doh") << endl;
}
catch (const filesystem_error &oops) {
cerr << oops.what() << '\n';
}
/etc/group: 1535
doh: filesystem error: cannot get file size: No such file or directory [doh]
If the optional error_code argument is given, nothing is thrown:
using namespace filesystem;
for (auto fn : {"/bin/cc", "/bin/cat"}) {
error_code ec;
string s = read_symlink(fn, ec);
if (ec)
cerr << fn << ": " << ec.message() << '\n';
else
cout << fn << " -> " << s << '\n';
}
/bin/cc -> gcc
/bin/cat: Invalid argument
An error_code in a boolean context is true iff
the last operation was bad.
Iteration
using namespace filesystem;
path home(getenv("HOME"));
path pub(home / "pub");
for (directory_entry d : directory_iterator(pub))
if (d.path().extension() == ".txt")
cout << d.path().filename() << '\n';
"hamlet.txt"
"common-words.txt"
"abcdefg.txt"
Recursive Iteration
using namespace filesystem;
path home(getenv("HOME"));
path pub(home / "pub");
for (const auto &d : recursive_directory_iterator(pub))
if (d.path().stem() == "README")
cout << d << '\n';
"/s/bach/a/class/cs253/pub/Example/README.txt"
A path is printed with "quotes" so we can read & write paths containing whitespace.
$ ls -lhog /etc/group
-rw-r--r-- 1 1.5K Nov 30 2022 /etc/group
status() returns a file_status object:
using namespace filesystem;
file_status s = status("/etc/group");
file_type t = s.type();
perms p = s.permissions();
if ((p & perms::owner_read) != perms::none)
cout << "readable by owner\n";
if (t == file_type::regular)
cout << "a regular file\n";
readable by owner
a regular file
using namespace filesystem;
const path home(getenv("HOME"));
auto fname(home / "pub/dwarfs");
if (ifstream in(fname); in.good())
for (string s; getline(in, s); )
cout << s << '\n';
else
cerr << "can’t open " << fname << " for reading.\n";
Bashful
Doc
Dopey
Grumpy
Happy
Sleepy
Sneezy
And …