29 Input/output library [input.output]

29.11 File systems [filesystems]

29.11.13 Class recursive_­directory_­iterator [fs.class.rec.dir.itr]

An object of type recursive_­directory_­iterator provides an iterator for a sequence of directory_­entry elements representing the files in a directory or in an implementation-defined directory-like file type, and its sub-directories.
namespace std::filesystem {
  class recursive_directory_iterator {
  public:
    using iterator_category = input_iterator_tag;
    using value_type        = directory_entry;
    using difference_type   = ptrdiff_t;
    using pointer           = const directory_entry*;
    using reference         = const directory_entry&;

    // [fs.rec.dir.itr.members], constructors and destructor
    recursive_directory_iterator() noexcept;
    explicit recursive_directory_iterator(const path& p);
    recursive_directory_iterator(const path& p, directory_options options);
    recursive_directory_iterator(const path& p, directory_options options,
                                 error_code& ec);
    recursive_directory_iterator(const path& p, error_code& ec);
    recursive_directory_iterator(const recursive_directory_iterator& rhs);
    recursive_directory_iterator(recursive_directory_iterator&& rhs) noexcept;
    ~recursive_directory_iterator();

    // [fs.rec.dir.itr.members], observers
    directory_options  options() const;
    int                depth() const;
    bool               recursion_pending() const;

    const directory_entry& operator*() const;
    const directory_entry* operator->() const;

    // [fs.rec.dir.itr.members], modifiers
    recursive_directory_iterator&
      operator=(const recursive_directory_iterator& rhs);
    recursive_directory_iterator&
      operator=(recursive_directory_iterator&& rhs) noexcept;

    recursive_directory_iterator& operator++();
    recursive_directory_iterator& increment(error_code& ec);

    void pop();
    void pop(error_code& ec);
    void disable_recursion_pending();

    // other members as required by [input.iterators], input iterators
  };
}
Calling options, depth, recursion_­pending, pop or disable_­recursion_­pending on an iterator that is not dereferenceable results in undefined behavior.
The behavior of a recursive_­directory_­iterator is the same as a directory_­iterator unless otherwise specified.
[Note
:
If the directory structure being iterated over contains cycles then the end iterator may be unreachable.
— end note
]

29.11.13.1 Members [fs.rec.dir.itr.members]

recursive_directory_iterator() noexcept;
Effects: Constructs the end iterator.
explicit recursive_directory_iterator(const path& p); recursive_directory_iterator(const path& p, directory_options options); recursive_directory_iterator(const path& p, directory_options options, error_code& ec); recursive_directory_iterator(const path& p, error_code& ec);
Effects: Constructs an iterator representing the first entry in the directory to which p resolves, if any; otherwise, the end iterator.
However, if
(options & directory_options::skip_permission_denied) != directory_options::none
and construction encounters an error indicating that permission to access p is denied, constructs the end iterator and does not report an error.
Postconditions: options() == options for the signatures with a directory_­options argument, otherwise options() == directory_­options​::​none.
Throws: As specified in [fs.err.report].
[Note
:
To iterate over the current directory, use recursive_­directory_­iterator(".") rather than recursive_­directory_­iterator("").
— end note
]
[Note
:
By default, recursive_­directory_­iterator does not follow directory symlinks.
To follow directory symlinks, specify options as directory_­options​::​follow_­directory_­symlink.
— end note
]
recursive_directory_iterator(const recursive_directory_iterator& rhs);
Postconditions:
  • options() == rhs.options()
  • depth() == rhs.depth()
  • recursion_­pending() == rhs.recursion_­pending()
recursive_directory_iterator(recursive_directory_iterator&& rhs) noexcept;
Postconditions: options(), depth(), and recursion_­pending() have the values that rhs.options(), rhs.depth(), and rhs.recursion_­pending(), respectively, had before the function call.
recursive_directory_iterator& operator=(const recursive_directory_iterator& rhs);
Effects: If *this and rhs are the same object, the member has no effect.
Postconditions:
  • options() == rhs.options()
  • depth() == rhs.depth()
  • recursion_­pending() == rhs.recursion_­pending()
Returns: *this.
recursive_directory_iterator& operator=(recursive_directory_iterator&& rhs) noexcept;
Effects: If *this and rhs are the same object, the member has no effect.
Postconditions: options(), depth(), and recursion_­pending() have the values that rhs.options(), rhs.depth(), and rhs.recursion_­pending(), respectively, had before the function call.
Returns: *this.
directory_options options() const;
Returns: The value of the argument passed to the constructor for the options parameter, if present, otherwise directory_­options​::​none.
Throws: Nothing.
int depth() const;
Returns: The current depth of the directory tree being traversed.
[Note
:
The initial directory is depth 0, its immediate subdirectories are depth 1, and so forth.
— end note
]
Throws: Nothing.
bool recursion_pending() const;
Returns: true if disable_­recursion_­pending() has not been called subsequent to the prior construction or increment operation, otherwise false.
Throws: Nothing.
recursive_directory_iterator& operator++(); recursive_directory_iterator& increment(error_code& ec);
Effects: As specified for the prefix increment operation of Input iterators, except that:
  • If there are no more entries at the current depth, then if depth() != 0 iteration over the parent directory resumes; otherwise *this = recursive_­directory_­iterator().
  • Otherwise if
    recursion_pending() && is_directory((*this)->status()) &&
    (!is_symlink((*this)->symlink_status()) ||
     (options() & directory_options::follow_directory_symlink) != directory_options::none)
    
    then either directory (*this)->path() is recursively iterated into or, if
    (options() & directory_options::skip_permission_denied) != directory_options::none
    
    and an error occurs indicating that permission to access directory (*this)->path() is denied, then directory (*this)->path() is treated as an empty directory and no error is reported.
Returns: *this.
Throws: As specified in [fs.err.report].
void pop(); void pop(error_code& ec);
Effects: If depth() == 0, set *this to recursive_­directory_­iterator().
Otherwise, cease iteration of the directory currently being iterated over, and continue iteration over the parent directory.
Throws: As specified in [fs.err.report].
Remarks: Any copies of the previous value of *this are no longer required to be dereferenceable nor to be in the domain of ==.
void disable_recursion_pending();
Postconditions: recursion_­pending() == false.
[Note
:
disable_­recursion_­pending() is used to prevent unwanted recursion into a directory.
— end note
]

29.11.13.2 Non-member functions [fs.rec.dir.itr.nonmembers]

These functions enable use of recursive_­directory_­iterator with range-based for statements.
recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept;
Returns: iter.
recursive_directory_iterator end(const recursive_directory_iterator&) noexcept;
Returns: recursive_­directory_­iterator().