---
name: "filesystem"
section: "3bobcat"
platform: "linux"
package: "libbobcat-dev"
version: "6.07.01-2"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/filesystem"
---

# filesystem(3bobcat)

class offering std::filesystem facilities

## NAME

FBB::Filesystem - class offering std::filesystem facilities

## SYNOPSIS

**#include \<bobcat/filesystem\>**\
 Linking option: *-lbobcat*

This header file also includes the *std::chrono* header file.

## DESCRIPTION

The Bobcat class **FileSystem** is a plain wrapper around the facilities offered by the **C++** *std::filesystem* namespace. **FileSystem** was developed because the use of the *std::filesystem* facilities is considered overly complex: too many free functions having signatures resembling **C**, and therefore not object-based. Its *std::filesystem::path* type offers several nice features which are then usable via the *path* member functions, but functions manipulating the file system aren’t members, but are defined as free functions requiring *path* arguments.

The class **FileSystem** offers almost all *std::filesystem* facilities via its member functions. Except for some (static) members all facilities operate on data stored inside **FileSystem** objects.

The class **FileSystem** is an extensive class: over-all it contains about 60 constructors, operators and members. It’ll probably take a while before a mental picture of what the class offers has been attained, but at least it embeds all components of the *std::filesystem* namespace.

Note:

- o

  The class **FileSystem** uses *std::chrono::file\_clock*, which is  available since the *C++-2a* standard: specify the *--std=c++2a* (or more recent) compiler option when using **FileSystem**.

## NAMESPACE

**FBB**\
 All constructors, members, operators and manipulators, mentioned in this man-page, are defined in the namespace **FBB**.

## INHERITS FROM

*FBB::FS* - internally used only, covered in this man-page

## TYPEDEFS AND ENUMS

**Typedefs:**

- o

  **DirEntry** - *std::filesystem::directory\_entry*

- o

  **DirIter** - *std::filesystem::directory\_iterator*

- o

  **EC** - *std::error\_code*

- o

  **FileClock** - *std::chrono::file\_clock*

- o

  **FileType** - *std::filesystem::file\_type*

- o

  **Path** - *std::filesystem::path*

- o

  **Perms** - *std::filesystem::perms*

- o

  **RecursiveIter** - *std::filesystem::recursive\_directory\_iterator*

- o

  **FileStatus** - *std::filesystem::file\_status*

- o

  **SystemClock** - *std::chrono::system\_clock*

**FSOptions:**

- o

  **enum FSOptions**:\
   contains the following values, inherited by *FileSystem*. Options up to *CP\_MASK* are primarily used by the *copy* member, options beyond *CP\_MASK* are used by *setPermissions*:

  ```
      NEW             copy is only performed if the destination
                      doesn’t yet exist
      REPLACE         copy is only performed if the destination
                      exists but it is replaced
      UPDATE          copy is only performed if the destination
                      is older than the filesystem entry to copy
      RECURSIVE       directories are recursively copied; can be
                      combined with CP_SYMLINKS, SKIP_SYMLINKS,
                      ONLY_DIRS
      CP_SYMLINKS     symlinks are copied as symlinks
      SKIP_SYMLINKS   symlinks are ignored
      ONLY_DIRS       only the directory structure is copied
                      other entries in directories are ignored
      SYMLINK         with copy: define a symlink to the current
                      entry
      HARDLINK        with copy: define a hard link to the current
                      entry
      FILE            with copy: only files are processed, not
                      directories
      CP_SYMLINK      copies a symlink to a symlink
      NEW_SYMLINK     defines a non-existing (directory) symlink
      NEW_LINK        create_hard-link
      CP_MASK         all the above enum values
      RESET           replace the current permissions
      ADD             add to the current permissions
      REMOVE          remove the specified permissions
  ```

All bit-wise operators are available for **FSOptions** values.

## STATIC DATA MEMBER

The class *FileSystem* defines one static data member: *std::error\_code s\_errorCode*. All *FileSystem* objects can use this *error\_code* object after calling their function call operator. E.g.,

```
    FileSystem fs;
    fs();
```

Once *fs()* has been called members called by *fs* accepting *error\_code* arguments receive *s\_error\_code* as their argument. It’s also possible to use other *error\_code* objects, or not to use *error\_code* arguments (which is the default). See also the description of the function call operator below.

## CONSTRUCTORS

*Path* arguments can also be arguments of types from which *Path* objects can be constructed (e.g., *std::string, char const \**, raw string literal).

*FileSystem* objects contain two data members: a *Path* and an  *EC \**. When *FileSystem* objects are initialized their *EC \** is set to 0.

- o

  **Filesystem()**:\
   The default constructor constructs an empty object, not using the class’s static *s\_errorCode* object;

-

  - o

  **Filesystem(Path const &path, bool useEC = true)**:\
   The object is initialized with a copy of *path*. By default *useEC* *== true*, in which case it uses the class’s static *s\_errorCode* object;

-

  - o

  **Filesystem(Path &&path, EC &ec)**:\
   The object is initialized with a copy of *path*, passing *ec* to members supporting *EC* arguments;

-

  - o

  **Filesystem(Path const &tmp, bool useEC = true)**:\
   The object moves *tmp* to its internal *path*. By default *useEC* *== true*, in which case it uses the class’s static *s\_errorCode* object;

-

  - o

  **Filesystem(Path &&tmp, EC &ec)**:\
   The object moves *tmp* to its internal *path*, passing *ec* to members supporting *EC* arguments.

Copy and move constructors (and assignment operators) are available.  The newly constructed or assigned object use the same *EC* specification as their source (right-hand side) objects.

## OVERLOADED OPERATORS

*Type* arguments can be arguments of type *FileSystem, Path* or types from which *Path* objects can be constructed (e.g., *std::string, char* *const \**, raw string literal).

- o

  **std::istream &operator\>\>(std::istream &in, FileSystem &rhs)**:\
   extracts a *path* specification from *in*, and initializes *rhs* with the extracted path;

-

  - o

  **std::ostream &operator\<\<(std::ostream &out, FileSystem const &rhs)**:\
   inserts the object’s *path* into *out*;

-

  - o

  **bool operator==(FileSystem const &lhs, FileSystem const &rhs)**:\
   returns *true* if *lhs* and *rhs* refer to the same file system entry. An exception is thrown if at least one argument doesn’t refer to an existing file system entry and the *lhs* operand hasn’t specified an *EC* (see *operator()()* below). This operator calls the member *sameAs* for its *lhs* argument;

-

  - o

  **FileSystem &operator/=(Type const &arg)**:\
   *arg* is appended to the object’s *path* data member. If the *path* data member did not already end in *’/’* then */arg* is appended;

-

  - o

  **FileSystem &operator+=(Type const &arg)**:\
   *arg* is appended to the object’s *path* data member;

-

  - o

  **FileSystem \[const\] &operator()(EC &ec = s\_errorCode) \[const\]**:\
   this operator activates passing *EC* arguments to member function accepting such arguments. By calling this operator without argument member functions receive *FileSystem’s s\_errorCode*. Alternatively another (e.g., local) *error\_code* object can be specified  which will then be passed to members accepting *error\_code* arguments. Example:

  ```
      std::error_code ec;
      FileSystem fs;
      fs(ec);
  ```

  Using *EC* arguments is configured separately for each *FileSystem* object. The member *noEC* can be used to suppress  passing  *EC* arguments to *std::filesystem* functions;

## MEMBER FUNCTIONS

*Type* arguments can be arguments of type *FileSystem, Path* or types from which *Path* objects can be constructed (e.g., *std::string, char* *const \**, raw string literal).

All members can use *EC* objects to prevent exceptions being thrown when the members cannot perform their tasks.

- o

  **FileSystem absolute() const**:\
   returns a *FileSystem* object containing the absolute path of the calling object’s *Path*, which does not have to exist. Relative directory specifications are kept: *absolute* simply prefixes the current working directory to the calling object’s *Path*;

-

  - o

  **FileSystem canonical() const**:\
   returns a *FileSystem* object containing the canonical absolute path of the calling object’s *Path*, from which all relative specifications have been removed. *Path* must refer to an existing file system entry;

-

  - o

  **bool copy(Type const &dest, FSOptions cpOptions = DEFAULT)**:\
   copies the object’s file system entry to *dest*. It is covered in detail in the section **COPYING FILE SYSTEM ENTRIES** below;

-

  - o

  **uintmax\_t count() const**:\
   returns the number of hard-link counts of the calling *FileSystem* object. The file system entry must exist;

-

  - o

  **char const \*c\_str() const**:\
   returns the calling object’s *PATH* specification as a NTBS;

-

  - o

  **static FileSystem cwd(\[EC &ec\])**:\
   this static member returns the current working directory (cwd). If the cwd cannot be determined then an exception is thrown, unless an *EC* argument is specified, in which case the *EC* argument provides information about the failure;

-

  - o

  **FileSystem destination() const**:\
   returns a *FileSystem* object containing the (symlink) destination of the calling object, which must refer to a symlink;

-

  - o

  **DirEntry directory() const**:\
   returns a *DirEntry* for the calling object. The calling object does not have to refer to a directory, and not even to an existing file system entry;

-

  - o

  **Ranger\<DirIter\> dirRange() const**:\
   returns a pair of directory iterators non-recursively visiting all entries referred to by the calling object, which must specify a directory name (see also the member *recursiveRange*). Example:

  ```
      for (auto const &entry: fs.dirRange())
          cout << entry << ’\n’;
  ```

-

  - o

  **static std::error\_code &errorCode()**:\
   this static member returns a reference to *FileSystem’s* static (modifiable) *EC* data member.

-

  - o

  **bool exists() const**:\
   returns *true* if the current object’s file system entry exists;

-

  - o

  **static bool exists(FileStatus status)**:\
   returns *true* if *status* indicates that the current file system entry exists (see also the member *status* below);

-

  - o

  **std::string extension() const**:\
   returns the extension (including the initial dot (.) of the calling object);

-

  - o

  **FileClock::time\_point fcModification() const**:\
   returns the *FileClock::time\_point* of the (existing) file system entry represented by the calling object;

-

  - o

  **std::string filename() const**:\
   returns the filename (i.e., the path name from which all but the last element has been removed). If the calling object doesn’t contain a filename (as with *./* or */*) then and empty *string* is returned;

-

  - o

  **bool hasExtension() const**:\
   returns *true* if the calling object’s *Path* has an extension;

-

  - o

  **bool hasFilename() const**:\
   returns *true* if the calling object’s *Path* contains characters after its final */* character;

-

  - o

  **bool isAbsolute() const**:\
   returns *true* if the calling object’s *Path* starts with */*;

-

  - o

  **bool isRelative() const**:\
   returns *true* if the calling object’s *Path* does not start with */*;

-

  - o

  **bool knownStatus() const**:\
   this member only returns *false* for *std::filesystem::file\_status{}*. The member *status* is probably more useful: non-existing entries show status values *FileType::not\_found* or *FileType::unknown*.\
   To check for specific statuses the functions\
   *bool is\_WHATEVER(file\_status status)* or\
   *bool is\_WHATEVER(path const &entry \[, EC &ec\])*\
   can also be used;

-

  - o

  **bool mkDir() const**:\
   returns *true* if the (plain) directory name stored in the calling oblect could be created. This member does not create nested sub-directories, but the directory name specified as the last (*/*-separated) component of the calling object’s *Path* is created if its parent directories already exist;

-

  - o

  **bool mkDir(Type const &reference) const**:\
   same as the previous member, but the created directory receives the same attributes (permissions) as *reference*;

-

  - o

  **bool mkDirs() const**:\
   returns true if the last component of the  calling object’s *Path* could be created and its parent components could either be created or already existed as directories. Only the directories are constructed, not their entries. Use the *copy* member (see section *COPYING* *FILE SYSTEM ENTRIES* below) to copy directories and their file system entries;

-

  - o

  **SystemClock::time\_point modification() const**:\
   returns the *SystemClock::time\_point* of the (existing) file system entry represented by the calling object;

-

  - o

  **FileSystem \[const\] &noEC() \[const\]**:\
   if the calling object uses an *EC*, then the *EC* won’t be used anymore after calling this member;

-

  - o

  **FileSystem parent() const**:\
   returns a *FileSystem* object initialized with the parent *Path* of the calling object. The *parent* is equal to the calling object’s *Path* from which its *filename* has been removed (returning an empty object if the calling object merely contains \`*/*’);

-

  - o

  **Path const &path() const**:\
   returns the current object’s *Path* data member. When inserting *path()* into an *ostream* *Path* is surrounded by double quotes. If that’s not required call the *string* member;

-

  - o

  **Perms permissions() const**:\
   returns the permissions of the calling object, which must refer to an existing file system entry. The returned *Perms* value consists of bitwise or-ed values of the *std::filesystem::perms enum class*, but can be statically cast to *mode\_t* values which are used as argument to [**chmod**(2)](/chmod/2.md);

-

  - o

  **Ranger\<\[Const\]Iter\> range() \[const\]**:\
   returns a pair of iterators visiting all components of the calling object’s *Path*.Example:

  ```
      for (auto const &comp: fs.range())
          cout << comp << ’\n’;
  ```

-

  - o

  **FileSystem relative() const**:\
   returns a copy of the calling object from which an initial \`*/*’ has been removed;

-

  - o

  **bool remove() const**:\
   returns *true* if the current object’s file system entry has been removed;

-

  - o

  **size\_t removeAll() const**:\
   returns the number of (recursively) removed file system entries starting at the calling object’s *Path*. The calling object doesn’t have to specify a directory;

-

  - o

  **bool rename(Type const &newName) const**:\
   returns *true* if the current file system entry could be renamed to *newName*. The calling object’s *Path* is not altered;

-

  - o

  **bool resize(std::uintmax\_t size) const**:\
   returns *true* if the current file system entry could be resized to *size*;

-

  - o

  **bool sameAs(Type const &other) const**:\
   returns *true* if *other* refers to the same file system entry as the calling object. It is called by *operator==* as its *lhs* member;

-

  - o

  **FileSystem &setCwd()**:\
   changes the current process’s current working directory to the directory specified by the calling object;

-

  - o

  **static FileSystem setCwd(Path const &path \[, EC &ec\])**:\
   this static member changes the current process’s current working directory to the directory specified by its *Path* argument;

-

  - o

  **FileSystem &setExtension(std::string const &ext)**:\
   changes the filename extension of the current object to *ext*. A dot (*.*) is used to separate the current object’s *stem* (see below) and the extension. The resulting file name only has a single dot;

-

  - o

  **FileSystem &setFilename(std::string const &newName)**:\
   changes the current object’s file name (including its extension) to *newName*. If the current object refers to an existing file system entry then that file system entry is kept as-is;

-

  - o

  **bool setModification(FBB::DateTime const &time)**:\
   changes the modification time of the current file system entry to the *time* time-specification;

-

  - o

  **bool setModification(SystemClock::time\_point const &time)**:\
   changes the modification time of the current file system entry to the *time* time-specification;

-

  - o

  **FileSystem \[const\] &setPermissions(PermType perms,**  **FSOptions opt = RESET) \[const\]**:\
   changes the permissions of the current file system entry to *perms*, which must be statically castable to *Perms*. Example:

  ```
              // change "entry’s" permissions to -rw-------
      FileSystem{ "entry" }.setPermissions(0600);
  ```

-

  - o

  **bool setType(FileType type, bool destination = true)**:\
   it’s unclear what this function is used for. It calls *filesystem::(symlink\_)status*, using *symlink\_status* when called as *type(false)*. It returns *false* if *type* doesn’t match the current file system entry referred, but the type itself isn’t modified;

-

  - o

  **uintmax\_t size() const**:\
   returns the size in bytes of the current file system entry;

-

  - o

  **FileStatus status(bool destination = true) const**:\
   returns the *filesystem::status* of the current file system entry. If the current object is a symlink and the symlink’s status is requested then call *status(false)*;

-

  - o

  **FileSystem stem() const**:\
   returns the file name of the current object without its extension;

-

  - o

  **std::string string() const**:\
   returns the current object’s *Path* data member as a *std::string*;

-

  - o

  **static FileSystem tmpDir(Type arg \[= true\])**:\
   this static member returns the file system’s directory which is by default used for temporary files. By default *tmpDir* uses *FileSystem::s\_errorCode* objct, when calling *tmpDir(false)* no *EC* object is used;

-

  - o

  **static FileSystem tmpDir(EC &ec)**:\
   this static member returns the file system’s directory  using the specified *EC* object when determining the temporay directory;

-

  - o

  **FileType type(bool destination = true) const**:\
   returns the *FileType* of the current file system entry. If the current object refers to a symlink call *type(false)* to receive the symlink’s type.

## COPYING FILE SYSTEM ENTRIES

The member *copy(Type const &dest, FSOptions cpOptions = DEFAULT)’s* first argument specifies the name of the copied file or directory. It’s second argument specifies the type of the copy-operation. Options can be combined using binary operators (usually *bit\_or*). The following combinations are valid:

- o

  *FILE* - unconditionally copies the current entry to *dest*;

- o

  *FILE \| NEW* - the current entry is copied to *dest* if *dest*  does not yet exist;

- o

  *FILE \| REPLACE* - the current entry is copied to *dest* if *dest* already exists;

- o

  *FILE \| UPDATE* - the current entry is only copied to *dest* if it is younger than *dest*;

- o

  *CP\_SYMLINK* - the current entry must be a symlink, *dest* may not yet exist and becomes a symlink to the same destination as the current entry’s destination;

- o

  *NEW\_LINK* - *dest* may not yet exist. It becomes a hard-link to the current entry. The current object must exist;

- o

  *NEW\_SYMLINK* - *dest* may not yet exist. It becomes a symlink to the current entry. If the current entry is itself a symlink then *dest* becomes a symlink to the current entry, and not to the entry the current object refers to. The current object does not have to be an existing file system entry;

- o

  *RECURSIVE* - the current entry is recursively copied to *dest*. If the current entry isn’t a directory then the entry itself is copied as if *RECURSIVE* was not specified;

- o

  *RECURSIVE \| CP\_SYMLINKS* - like using *RECURSIVE* but existing symlinks are copied as symlinks;

- o

  *RECURSIVE \| ONLY\_DIRS* - like using *RECURSIVE* but only the directory structure is copied;

- o

  *RECURSIVE \| SKIP\_SYMLINKS* - like using *RECURSIVE* but existing symlinks are not copied;

## EXAMPLE

```
#include <iostream>
#include <string>
#include <exception>
#include <bobcat/filesystem>
using namespace std;
using namespace FBB;
int main(int argc, char **argv)
{
    if (argc == 1)
    {
        cout << "1st arg: an existing file\n"
                "2nd arg (optional): a directory owned by the caller\n";
        return 1;
    }
    FileSystem fs{ argv[1] };
    if (not fs.exists())
        cout << "No such file " << argv[1] << ’\n’;
    else
        cout << "last modification date of " << argv[1] << ": " <<
                                            fs.modification() << ’\n’;
    cout << oct << "Permissions: 0" <<
                    static_cast<size_t>(fs.permissions()) << dec << ’\n’;
    if (argc > 2)
    {
        cout << "Entries of " << argv[2] << ":\n";
        FileSystem fs2{ argv[2] };
        for (auto const &entry: fs2.dirRange())
            cout << "   " << entry << ’\n’;
        cout << fs2.errorCode().message() << ’\n’;
    }
}
```

## FILES

*bobcat/filesystem* - defines the class interface

## SEE ALSO

[**bobcat**(7)](/bobcat/7.md), [**chmod**(2)](/chmod/2.md), [**datetime**(3bobcat)](/datetime/3bobcat.md), [**ranger**(3bobcat)](/ranger/3bobcat.md)

## BUGS

None Reported.

## BOBCAT PROJECT FILES

- o

  *https://fbb-git.gitlab.io/bobcat/*: gitlab project page;

Debian Bobcat project files:

- o

  *libbobcat6*: debian package containing the shared library, changelog and copyright note;

- o

  *libbobcat-dev*: debian package containing the static library, headers, manual pages, and developer info;

## BOBCAT

Bobcat is an acronym of \`Brokken’s Own Base Classes And Templates’.

## COPYRIGHT

This is free software, distributed under the terms of the GNU General Public License (GPL).

## AUTHOR

Frank B. Brokken (**f.b.brokken@rug.nl**).
