CS253: Software Development with C++

Fall 2020

Filesystem

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:

path

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"

filesystem_error

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]

error_code

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';
"abcdefg.txt"
"hamlet.txt"
"common-words.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.

file_status

$ 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

path and fstream

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 …

absolute()composes an absolute pathremove()removes a file or empty directory
canonical()/weakly_canonical()composes a canonical pathremove_all()removes file/directory & contents, recursively
relative()/proximate()composes a relative pathrename()moves or renames a file or directory
copy()copies files or directoriesresize_file()truncate or zero-fill
copy_file()copies file contentsspace()determines available free space
copy_symlink()copies a symbolic linkstatus()determines file attributes
create_directory()/create_directories()creates new directorysymlink_status()determines symlink target attributes
create_hard_link()creates a hard linktemp_directory_path()directory for temporary files
create_symlink()/create_directory_symlink()creates a symlinkis_block_file()is this a block device?
current_path()returns/sets the current directoryis_character_file()is this a a character device?
exists()does this path exist?is_directory()is this a a directory?
equivalent()do two paths refer to the same file?is_empty()is this a an empty file or directory?
file_size()returns the size of a fileis_fifo()is this a a named pipe?
hard_link_count()returns the number of hard linksis_other()is this a other file?
last_write_time()gets/sets time of the last data changeis_regular_file()is this a regular file?
permissions()modifies file access permissionsis_socket()is this a named IPC socket?
read_symlink()obtains the target of a symbolic linkis_symlink()is this a symbolic link?