3

There are no any examples of the functions ready for use on c++ without additional libs to Copy recursive files and folders to the new location.

Some alternative to system("cp -R -f dir"); call.

I'm only found this Recursive directory copying in C example on the thread answer, but its not ready for use and I'm not sure that this example is correct to start with.

Maybe somebody have working example on the disk?

Community
  • 1
  • 1
abrahab
  • 2,430
  • 9
  • 39
  • 64
  • Because it's depending on OS, no ? – Pierre Apr 05 '16 at 13:46
  • @Pierre I do not dream about portable solution. Only Unix systems, maybe with posix. – abrahab Apr 05 '16 at 13:48
  • 5
    for now, boost::filesystem. Once c++17 is out, std::filesystem. – Richard Hodges Apr 05 '16 at 13:49
  • Who vote for "-1" ? Are you really think that each developer must reinvent the bicycle? – abrahab Apr 05 '16 at 13:50
  • @RichardHodges It would not be desirable to depend on boost only for this. – abrahab Apr 05 '16 at 13:52
  • @abrahab you asked for a working example on disk. boost is on pretty much every c++ developer's disk. Why would we reinvent a perfectly fantastic wheel that works on every OS flawlessly? – Richard Hodges Apr 05 '16 at 13:56
  • There was a long (and incorrect in my view) standing that including directory handling capabilities in C++ is bad, since not every system where C++ is used has directories. Of course, this is total nonsense - not every system has files, yet C++ allows you to open files. – SergeyA Apr 05 '16 at 13:56
  • @RichardHodges, despite popular opinion, `boost::filesystem` doesn't work on *any* system. It only works on Windows and Posix. – SergeyA Apr 05 '16 at 13:58
  • 1
    @SergeyA that pretty much covers anything that supports the concept of directories doesn't it? – Richard Hodges Apr 05 '16 at 14:00
  • @RichardHodges, not sure. Do mainfraimes have directories? I never seen one, so I can't tell. – SergeyA Apr 05 '16 at 14:01
  • @RichardHodges Not every server have boost, so I need to upload it myself with program and take care of it. I do not want to have dependencies, carry extra files and take care about them only for this little task, that can be solved with posix lib on the system and one function. – abrahab Apr 05 '16 at 14:09
  • you can link boost to your executable as a static library. It becomes part of your object code. There will be no external dependencies at all. – Richard Hodges Apr 05 '16 at 14:10
  • @RichardHodges Okey, lats imagine for a moment that it's not a problem to use boost, but we are back to the question where is already working example of recursive copy with boost? It does not removes the question about reinventing the wheel. There are no working examples on SO to solve this task with boost. – abrahab Apr 05 '16 at 14:16
  • @abrahab here's an example of a recursive directory search. the copy bit would be trivial. http://stackoverflow.com/questions/18233640/boostfilesystemrecursive-directory-iterator-with-filter – Richard Hodges Apr 05 '16 at 14:20

2 Answers2

3

Here is a complete running example for recursive copying with POSIX and standard library functions.

#include <string>
#include <fstream>

#include <ftw.h>
#include <sys/stat.h>

const char* src_root ="foo/";
std::string dst_root ="foo2/";
constexpr int ftw_max_fd = 20; // I don't know appropriate value for this

extern "C" int copy_file(const char*, const struct stat, int);

int copy_file(const char* src_path, const struct stat* sb, int typeflag) {
    std::string dst_path = dst_root + src_path;
    switch(typeflag) {
    case FTW_D:
        mkdir(dst_path.c_str(), sb->st_mode);
        break;
    case FTW_F:
        std::ifstream  src(src_path, std::ios::binary);
        std::ofstream  dst(dst_path, std::ios::binary);
        dst << src.rdbuf();
    }
    return 0;
}

int main() {
    ftw(src_root, copy_file, ftw_max_fd);
}

Note that the trivial file copy using the standard library does not copy the mode of the source file. It also deep copies links. Might possibly also ignore some details that I didn't mention. Use POSIX specific functions if you need to handle those differently.

I recommend using Boost instead because it's portable to non POSIX systems and because the new c++ standard filesystem API will be based on it.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Thank you! I will test it ASAP. When standard will have filesystem API, Maybe, I will migrate to it. :-) Now, I'm already using all headers from your example at my `Utils.h` except `ftw.h`. So, it's as easy as it can be to add only one include), and I do not need portability :) – abrahab Apr 05 '16 at 17:46
  • A little note for all SO members, who will use this function. The `dst_root` must exists on the disk before execute the function. – abrahab Apr 05 '16 at 18:09
2

Standard C++ does not have the concept of a directory, only files. For what you wish to do you should probably just use Boost Filesystem. It's worth getting to know. Otherwise, you can make OS-dependent calls from your C++ app.

See also this SO thread:

How do you iterate through every file/directory recursively in standard C++?

Community
  • 1
  • 1
Bizmarck
  • 2,663
  • 2
  • 33
  • 48
  • How do boost do that without OS calls? maybe boost use posix lib or something like that? – abrahab Apr 05 '16 at 13:59
  • @abrahab Boost is open source, so you can look at their source code to determine how they do it for POSIX systems. – callyalater Apr 05 '16 at 14:04
  • 2
    @abrahab boost detects the target system at compile time and selects the correct code for the target. – Richard Hodges Apr 05 '16 at 14:07
  • @abrahab learn more about boost. It's very famous and many features of it were incorporated into C++ standard. So is boost file system which was included in C++ TR2 as stated in the other answer so that may be in the future C++ standard and you'll have crossplatform directory traversing – phuclv Apr 05 '16 at 14:24