31

I need a filesystem library for use with a C++11-capable compiler or a C++14-capable one - so it can't be be from C++17.

Now, I know that the filesystem library going into C++17 is based based on Boost::Filesystem; but - are they similar enough for me to use the Boost library and then seamlessly switch to the standard version at a later time, without changing more than, say, a using statement? Or are there (minor/significant) differences between the two? I know that for the case of variant, the Boost and the standard library versions differ quite a bit.

einpoklum
  • 118,144
  • 57
  • 340
  • 684

3 Answers3

26

There are a number of differences. Some were, I believe, Boost changes that were never propagated. For example, there is no path.filename_is_dot() query (as discussed below, it would be less useful in std::filesystem anyway).

There was also a good bit of late-breaking news on this front:

  1. Support for non-POSIX-like filesystems:
    • Specify whether a string is OS-native or POSIX-like (or let the implementation decide, which is (still) the default)
    • An implementation may define additional file types (beyond regular, directory, socket, etc.)
    • An implementation may define file_size for a directory or device file
  2. filename(), normalization, and relative/absolute conversions redefined (examples for POSIX):
    • path("foo/.").lexically_normal()=="foo/" (is the opposite in Boost)
    • path("foo/").filename()=="" (is path(".") in Boost)
    • remove_filename() leaves the trailing slash and is thus idempotent (it assigns parent_path() in Boost)
    • path(".profile").extension()=="" (is the whole name in Boost)
    • path decompositions and combinations can preserve things like alternate data stream names that are normally invisible
    • path("foo")/"/bar"=="/bar" (is path("foo/bar") in Boost), which allows composing relative file names with others (absolute or relative) and replaces Boost's absolute()
    • Boost's system_complete() (which takes only one argument) is renamed to absolute()
    • canonical() thus takes only one argument (fixed in a DR)
    • lexically_relative() handles .. and root elements correctly
    • permissions() takes more arguments (Boost combines them into a bitmask)

Note that Boost.Filesystem v4 is under development and is supposed to be C++17-compatible (but therefore incompatible in many respects with v3).

Davis Herring
  • 36,443
  • 4
  • 48
  • 76
  • Can you elaborate a bit beyond just linking? Also, have these changes not applied also to Boost filesystem? – einpoklum Sep 18 '17 at 10:38
  • So, is Windows' filesystem considered "non-POSIX" because of the drives and the backslashes? Or are we talking about something else? – einpoklum Sep 19 '17 at 08:10
  • 1
    Windows "is POSIX" despite the drives (which actually have a POSIX analogy in `//worms/share/foo`) and backslashes, but only because certain unusual things like ADS names are either ignored or hidden by the implementation. ("Non-POSIX" includes things like "has no relative paths" or so.) – Davis Herring Sep 19 '17 at 12:58
  • C:\ is a perfectly fine filename in POSIX, and I am reasonably sure windows can't handle that and many other POSIX filenames and features, so while it can be emulated, windows (the win32 subsystem) is certainly not POSIX. – Remember Monica Dec 21 '18 at 11:09
  • @MarcLehmann: Sure, but how does that affect the statement that, for the purposes of file system *structure*, this interface considers it POSIX-like? – Davis Herring Dec 21 '18 at 14:17
  • List of differences is much longer. For example, function `copy_directory()` does not even exist in std::filesystem. – BЈовић Sep 03 '19 at 09:43
  • @BЈовић : It was changed into an overload of `create_directory` as the [documentation](https://www.boost.org/doc/libs/1_71_0/libs/filesystem/doc/reference.html#copy_directory) said it should be. I don’t know if that warrants specific attention or not. – Davis Herring Sep 24 '19 at 18:09
8

Caveat: This answer does not reflect several last-minute changes before C++17 was finalized. See @DavisHerring's answer.


The Boost filesystem inserter and extractor use & as the escape character for " and &.

The standard will use std::quoted (which uses \ by default) to escape ", which in turn use \\ to escape \, see this reference.

Demo

It is likely the only one difference between them.

The reason for that difference can be found at N3399

einpoklum
  • 118,144
  • 57
  • 340
  • 684
Danh
  • 5,916
  • 7
  • 30
  • 45
  • I'm not really finding an explanation at the link for why use & at all as an escape character, that seems very weird to me. But thanks. – einpoklum Dec 01 '16 at 09:17
  • 1
    @einpoklum The Boost folk had used `&` for a long time, I don't know why they chose it, it's unlikely they will change it. The standard folk want to make it consistent across all library. – Danh Dec 01 '16 at 09:18
  • "It is likely the only one difference between them." This is far from correct. – cpplearner Jan 26 '17 at 18:28
0

Another nasty difference:

if (!std::filesystem::exists("/I/dont/exist", error)) {
    if (error) <-- this is **false**
}

if (!boost::filesystem::exists("/I/dont/exist", error)) {
    if (error) <--- this is **true**
}
skoperst
  • 2,259
  • 1
  • 23
  • 35