# boost/filesystem/operations.hpp

Introduction
Header synopsis
Class directory_iterator
Constructors
Destructor
Other_functions
Operations functions
exists
is_directory
is_empty
create_directory
remove
remove_all
rename
copy_file
initial_directory
complete
system_complete

## Introduction

The boost/filesystem/operations.hpp header provides operations on files and directories.

These operations traffic in paths; see boost/filesystem/path.hpp documentation.

For file I/O streams, see boost/filesystem/fstream.hpp documentation.

The Filesystem Library's Common Specifications apply to all member and non-member functions supplied by this header.

## Header boost/filesystem/operations.hpp synopsis

    namespace boost
    {
      namespace filesystem
      {

        class directory_iterator
        {
        public:
          typedef path                     value_type;
          typedef std::ptrdiff_t           difference_type;
          typedef const path *             pointer;
          typedef const path &             reference;
          typedef std::input_iterator_tag  iterator_category;

          directory_iterator();
          explicit directory_iterator( const path & directory_ph );

          // other functions
          // ...
        };

        bool exists( const path & ph );
        bool is_directory( const path & ph );
        bool is_empty( const path & ph );

        void create_directory( const path & directory_ph );
        bool remove( const path & ph );
        unsigned long remove_all( const path & ph );
        void rename( const path & from_path,
                     const path & to_path );
        void copy_file( const path & source_file,
                        const path & target_file );

        const path & initial_path();
        path current_path();
        path complete( const path & ph,
                       const path & base = initial_path() );
        path system_complete( const path & ph );

      } // namespace filesystem
    } // namespace boost

## Class directory_iterator

Class directory_iterator provides a C++ standard conforming input iterator which accesses the contents of a directory.

The value type is boost::filesystem::path, so dereferencing a directory_iterator yields a path to a file or directory contained within the directory represented by the directory-path argument supplied at construction. The path returned by dereferencing a directory_iterator is composed by appending the name of the directory entry to the directory path supplied at construction.

The order of the path entries returned by dereferencing successive increments of a directory_iterator is unspecified. Thus depending on the ordering provided by a particular implementation will result in non-portable code.

A path returned by dereferencing a directory_iterator is, if representing a directory, suitable for use as an argument to Filesystem Library functions specified as accepting paths or directory paths. If not representing a directory, the dereferenced path is suitable for use as an argument to Filesystem Library functions specified as accepting paths or file paths, or C++ Standard Library functions specified as taking file names. The leaf of a path returned by dereferencing a directory_iterator will never be `".."` or `"."`.

Note: The implication of the above requirement is that if an operating system's directories can contain entries which are not usable by Filesystem Library or Standard Library functions, these entries will be skipped during directory iteration. Such entries are by definition non-portable, but can always be accessed via the native operating system API if required.

### Constructors

> `directory_iterator();`

> Effects: Constructs a directory_iterator having the past-the-end value as described in the C++ standard, section 24.1.

> `explicit directory_iterator( const path & directory_ph );`

> Effects: Constructs a directory_iterator with a value representing the first path in directory_ph, or if `empty(directory_ph)`, the past-the-end value.

> Throws: if `!exists( directory_ph )`

> Note: To iterate over the current directory, write `directory_iterator(current_path())` rather than `directory_iterator("")`.

### Other functions

Class directory_iterator also supplies all the other functions required by the C++ standard clause 24 for input iterators, such as operator==, operator++, and operator*.

## Non-member functions

The non-member functions provide common operations on files and directories. They follow traditional practice of the C and C++ standard libraries, except that they:

- Traffic in paths rather than `char*`'s, for much enhanced portability.
- Report errors by throwing exceptions, for safer and better error handling.
- Tighten specifications slightly, for improved portability.

Rationale: Functions which already exist in the C++ Standard Library, such as remove() and rename(), retain the same names and general behavior in the Filesystem Library, to minimize surprises.

Rationale: Some errors which might at first glance appear to be preconditions are not specified as such, but instead will throw exceptions. This is because the possibility of race-conditions makes it unreliable to test for preconditions before calling the function. As a design practice, preconditions are not specified when it is not reasonable for a program to test for them before calling the function.

Empty path rationale: Some errors, particularly function arguments of empty paths, are specified both in Precondition and in Throws paragraphs. A non-empty path is specified as a precondition because an empty path is almost certainly an error, the error meets the usual criteria for Preconditions as specified in the C++ Standard clause 17, and user pre-detection of the error does not suffer from the precondition race problem described above. The error condition is also specified in the Throws paragraph to ensure that the error results in well-defined rather than implementation-defined behavior, and because existing practice for the equivalent operating system function is usually to treat an empty path as an error. The intended use of the Filesystem Library in script-like programs makes undefined behavior particularly unattractive.

Naming Rationale: See class path Naming Rationale.

### exists

> `bool exists( const path & ph );`

> Returns: True if the operating system reports the path represented by ph exists, else false.

> Note: Even if `exists( ph ) == true`, there is no guarantee that it will be possible to perform other operations on the file or directory. Access rights or other security concerns, for example, may cause other operations to fail.

> Note: `exists("")` is valid and returns false;

### is_directory

> `bool is_directory( const path & ph );`

> Returns: True if the operating system reports the path represented by ph is a directory, else false.

> Throws: if `!exists(ph)`

> Rationale: Treating `!exists(ph)` as an exception rather than just returning false came about because in real code `!exists(ph)` has often been the first indicate of a programming error. A compound function returning `exists(ph) && is_directory(ph)` can always be added later.

### is_empty

> `bool is_empty( const path & ph );`

> Returns: True if the operating system reports the path represented by ph is an empty file or empty directory, else false.

> Throws: if `!exists(path)`

### create_directory

> `void create_directory( const path & directory_ph );`

> Precondition: `!directory_ph.empty()`

> Postcondition: `exists(directory_ph) && is_directory(directory_ph) && is_empty(directory_ph)`

> Throws: if `directory_ph.empty() || exists(directory_ph)) || !exists(directory_ph/".."))`. See empty path rationale.

### remove

> `bool remove( const path & ph );`

> Precondition: `!ph.empty()`

> Returns: The value of `exists( ph )` prior to the establishment of the postcondition.

> Postcondition: `!exists( ph )`

> Throws: if`ph.empty() || (exists(ph) && is_directory(ph) && !is_empty(ph))`. See empty path rationale.

> Rationale: Does not throw when `!exists( ph )` because not throwing is:

> - Slightly easier-to-use for many common use cases.
> - Slightly higher-level because it implies use of postcondition semantics rather than effects semantics, which would be specified in the somewhat lower-level terms of interactions with the operating system.

> There is, however, a slight decrease in safety because some errors will slip by which otherwise would have been detected. For example, a misspelled path name could go undetected for a long time.

> The initial version of the library threw an exception when the path did not exist; it was reluctantly changed to reflect user complaints.

### remove_all

> `unsigned long remove_all( const path & ph );`

> Precondition: `!ph.empty()`

> Postcondition: `!exists( ph )`

> Returns: The number of files and directories removed.

> Throws: if`ph.empty()`. See empty path rationale.

### rename

> `void rename( const path & source, const path & target );`

> Precondition: `!source.empty() && !target.empty()`

> Effects: Changes the name of file or directory source to target. Specifically:

> Source | Target | Result is "as if" these actions occur
> !exists() |  | Throw filesystem_error. Note that !exists() covers the source.empty() case.
> | target.empty() | Throw filesystem_error. See create_directory() rationale.
> | exists() && !is_directory() | Throw filesystem_error.
> !is_directory() | !exists() | If !exists( target / ".." ) throw filesystem_error. Otherwise, the source.leaf() name is changed to target.leaf(), and if source / ".." resolves to a different directory than target / "..", the renamed source file is moved there.
> !is_directory() | is_directory() | The source file is moved to the target directory.
> is_directory() | !exists() | If !exists( target / ".." ) throw filesystem_error. Otherwise, the source.leaf() name is changed to target.leaf(), and if system_complete(source.banch_path()) resolves to a different directory than system_complete(target.branch_path()), the renamed source directory is moved there.
> is_directory() | is_directory() | The source directory is moved from source / ".." to target, becoming a sub-directory of target.

> Postconditions: `!exists(source) && exists(target)`, and the source file or directory contents and attributes are otherwise unchanged.

> Throws: See Effects table above. See empty path rationale.

> Rationale: Because rename is logically the same operation as move, there is no need for a separate move function. The choice of the name is based on existing practice in the C, C++, and POSIX libraries, and because the name move implies physical file movement, which does not in fact occur.

> Note: Some operating systems with multiple roots do not allow rename operations between roots, and such an attempted rename with throw a filesystem_error exception.. Implementations should not take heroic efforts, such as switching to a copy mode, to make an otherwise failing rename succeed across roots.

### copy_file

> `void copy_file( const path & source_file, const path & target_file );`

> Precondition: `!source.empty() && !target.empty()`

> Effects: Copies the file represented by source_file to target_file.

> Throws: if `!exists(source_file) || is_directory(source_file) || exists(target_file) || target_file.empty() || !exists(to_file_path/".."))`. See empty path rationale.

### initial_path

> `const path & initial_path();`

> Effects: The first time called, stores the path returned by current_path().

> The preferred implementation would be to call initial_path() during program initialization, before the call to main(). This is, however, not possible with changing the C++ runtime library.

> Returns: A reference to the stored path.

> Rationale: The semantics, in effect, turn a dangerous global variable into a safer global constant. The preferred implementation requires runtime library support, so alternate semantics are supplied for those implementations which cannot change an existing the runtime library.

> Note: It is good practice for a program dependent on initial_path() to call it immediately upon entering main(). That protects against another function altering the current working directory (using a native platform function) before the first call to initial_path().

### current_path

>     path current_path();

> Returns: The current path as maintained by the operating system.

> Postcondition: `current_path().is_complete()`

> Note: The equivalent POSIX function is getcwd(). The equivalent Windows function is GetCurrentDirectoryA().

> Warning: The current path maintained by the operating system is in-effect a dangerous global variable. It may be changed unexpectedly by a third-party or system library function, or by another thread. For a safer alternative, see initial_path().

> Rationale: Although dangerous, the function is useful in dealing with other libraries. The current_path() name was chosen to emphasize that the function returns a complete path, not just a single directory name.

### complete

> `path complete( const path & ph, const path & base = initial_path() );`

> Precondition: `!ph.empty() && base.is_complete() && (ph.is_complete() || !ph.has_root_name())`

> Effects: Composes a complete path from `ph` and `base`, using the following rules:

> For single-root operating systems (POSIX-like systems, for example), if `ph.empty()` or `ph.is_complete()`, the composed path is `ph`, otherwise the composed path is `base/ph`.

> For multi-root operating systems (Windows, Classic Mac, many others), the rules are give by this table:

> | `ph.has_root_directory()` | `!ph.has_root_directory()`
> `ph.has_root_name()` | `ph` | `(precondition failure)`
> `!ph.has_root_name()` | `base.root_name() / ph` | `base / ph`

> Returns: The composed path.

> Postcondition: For the returned path, `p,` `p.is_complete()` is true.

> Throws: On precondition failure. See empty path rationale.

> Note: When portable behavior is required, use complete(). When operating system dependent behavior is required, use system_complete().

> Portable behavior is preferred when dealing with paths created internally within a program, particularly where the program should exhibit the same behavior on all operating systems.

> Operating system dependent behavior is preferred when dealing with paths supplied by user input, reported to program users, or which should result in program behavior familiar to and expected by program users. The simple_ls.cpp program, for example, operates on a path supplied in the native operating system format, so uses system_complete() to ensure that the path behaves as expected for the particular operating system.

> Rationale: The `!ph.has_root_name()` portion of the precondition disallows the error condition of `ph.root_name()` being not equivalent to `base.root_name()`. The restriction is broader that would appear necessary, in that is also prohibits the case where they are equivalent. There is, however, no portable way to express the root_name() equivalence requirement.

### system_complete

> `path system_complete( const path & ph );`

> Precondition: `!ph.empty()`

> Effects: Composes a complete path from `ph`, using the same rules used by the operating system to resolve a path passed as the filename argument to standard library open functions.

> For POSIX-like systems, system_complete( ph ) has the same semantics as `complete( ph, current_path() )`.

> For Widows, system_complete( ph ) has the same semantics as `complete( ph, current_path() )` if ph.is_complete() || !ph.has_root_name() or ph and base have the same root_name(). Otherwise it acts like `complete( ph, kinky )`, where `kinky` is the current directory for the `ph.root_name()` drive. This will be the current directory of that drive the last time it was set, and thus may well be residue left over from some prior program run by the command processor! Although these semantics are often useful, they are also very error-prone, and certainly deserve to be called "kinky".

> Returns: The composed path.

> Postcondition: For the returned path, `p,` `p.is_complete()` is true.

> Throws: If `ph.empty()`. See empty path rationale.

> Note: See complete() note for usage suggestions.

> Warning: This function relies on a global variable (current_path()), and so tends to be more error-prone than the similar function complete(). This function is doubly dangerous on Windows, where under cross-drive conditions it may be relying on a directory set by a prior program run by the command processor.

© Copyright Beman Dawes, 2002

Revised 10 January, 2003