how to perform boost::filesystem copy_file with overwrite

47,866

Solution 1

There's a third enum argument to copy_file, boost::filesystem::copy_option::overwrite_if_exists

copy_file(source_path, destination_path, copy_option::overwrite_if_exists);

https://www.boost.org/doc/libs/1_75_0/libs/filesystem/doc/reference.html

Solution 2

Beware of boost::copy_file with copy_option::overwrite_if_exists! If the destination file exists and it is smaller than the source, the function will only overwrite the first size(from_file) bytes in the target file.

At least for me this was a caveat since I presumed copy_option::overwrite_if_exists affects files and not content

Solution 3

Test if the destination file exists first and if it does then remove it :

if (exists (to_fp))
    remove (to_fp);
copy_file (from_fp, to_fp);

Or if you're worried about the file appearing between the test and the copy then you could write to a temporary file and then rename it to the destination file.

Solution 4

Is there an elegant way to use the boost copy_file function and overwrite the target file?

Apparently there's no direct API to do this.

Or is it better to simply use the Windows API? My current target platform is Windows, but I prefer to use STL and boost where possible to keep my code platform independent.

From the documentation:

A proposal, N1975, to include Boost.Filesystem in Technical Report 2 has been accepted by the C++ Standards Committee. The Boost.Filesystem library will stay in alignment with the TR2 Filesystem proposal as it works its way through the TR2 process. Note, however, that namespaces and header granularity differs between Boost.Filesystem and the TR2 proposal.

Which strongly suggests that sticking with boost::filesystem is a good idea.

Share:
47,866
Dani van der Meer
Author by

Dani van der Meer

Updated on February 02, 2021

Comments

  • Dani van der Meer
    Dani van der Meer about 3 years

    The Windows API function CopyFile has an argument BOOL bFailIfExists that allows you to control whether or not you want to overwrite the target file if it exists.

    The boost::filesystem copy_file function has no such argument, and will fail if the target file exists. Is there an elegant way to use the boost copy_file function and overwrite the target file? Or is it better to simply use the Windows API? My current target platform is Windows, but I prefer to use STL and boost where possible to keep my code platform independent.

    Thank you.

  • Dani van der Meer
    Dani van der Meer almost 15 years
    Yes this is possible. But what if the copy operation fails? You already deleted the target. It doesn't have the same transaction-like semantics as CopyFile.
  • jon-hanson
    jon-hanson almost 15 years
    Does the rename alternative not give you this? Anyway from looking at the boost source the API doesn't allow you to optionally overwrite the file. You could suggest this to them as an improvement. In the meantime you could take your own copy of the boost copy_file function and modify it to take an extra "overwrite" bool parameter.
  • Dani van der Meer
    Dani van der Meer almost 15 years
    Well, I guess the rename logic will work, but I was hoping there was something in the library that solves this, and that I won't have to solve it myself :). I will try to suggest it as an improvement. I think this is a logical and helpful feature. Anyway, thanks for your help. I will probably use CopyFile for now.
  • Gaetano Mendola
    Gaetano Mendola almost 15 years
    Dani, the purpose to use boost is to write portable code, why to being so lazy you jeopardize the main reason to use boost ?
  • Dani van der Meer
    Dani van der Meer almost 15 years
    Portability is definitely an important reason for using Boost, but not necessarily the main reason. I would argue that the main reason for using a library like boost, but also the Windows API, is not having to implement basic functionality yourself (and test, debug, etc.). In this case these two reasons conflict, and I have to make the right trade-off. What is the right trad-off is of course a matter of opinion :).
  • Dani van der Meer
    Dani van der Meer over 14 years
    I decided to accept this answer, even though it is not a complete answer to the question. Apparently there is no better answer, and this answer describes the best approach.
  • jon-hanson
    jon-hanson over 14 years
    You might want to raise it with boost. Obviously Windows supports this, and Unix does through the O_CREAT & O_EXCL flags to open(), so I don't see why boost can't support it as well.
  • Dani van der Meer
    Dani van der Meer about 14 years
    Thanks anno. I wasn't aware of this. It seems that this option was added sometime between version 1.35 that I was using when I asked the question, and version 1.41 that I'm using now. I can't find the change in the change history of the library. But anyway, problem solved. I'm not sure if I should now accept your answer, maybe I'll ask on meta.
  • Dani van der Meer
    Dani van der Meer over 13 years
    I tried to reproduce on my platform (Windows), but couldn't. the overwrite does affect the complete file, regardless of size. What platform did you test on?
  • Vitaly P
    Vitaly P over 13 years
    IFAIK copy_option::overwrite_if_exists only exists on *nix (at least in boost-1.44 for filesystem v2). But you can easily see it in the the source code, the file is opened for writing with O_WRONLY but without O_TRUNC flag set.
  • Dani van der Meer
    Dani van der Meer over 13 years
    I am using boost 1.41. copy_option::overwrite_if_exists exists also for Windows. copy_file calls win32 API CopyFile (the A or W version) with bFailIfExists according to the option you pass to boost::copy_file. So possibly the behavior for Windows and POSIX is different?
  • Vitaly P
    Vitaly P over 13 years
    Yes it is different. I just submitted the bug to boost. See ISSUE #4930 (svn.boost.org/trac/boost/ticket/4930)
  • Dani van der Meer
    Dani van der Meer over 13 years
    Beware: there seems to be an issue with this third argument in the POSIX implementation. See answer by Vitaly.
  • Vitaly P
    Vitaly P over 13 years
    According to boost this issue has been just fixed in rev. 67067 (so I expect it will be included in the upcoming boost-1.46)
  • Drew Dormann
    Drew Dormann over 9 years
    @DanivanderMeer for the benefit of visitors to this page, that bug was fixed years ago.