Page 1 of 2

Copying a Directory

Posted: Thu Apr 28, 2005 11:01 pm
by Tyler
Per our previous discussion over at: http://forums.wxwidgets.org/viewtopic.php?t=1833 I finally got around to laying down the copy dir function. I think it's pretty handy. Thanks for the input on it. I incorporated the ideas from the thread. Please edit it if you think it's bloated, and if it's not usefull to anyone then my appologies for the following graffiti:

Code: Select all

// =================================================================
//	Date:		04/28/05
//	Author:		... doesn't matter ...
//	Platforms:	Written and tested under Win XP
//  Compiler:	MSVC++ 6.0
//	wxWidgets:	Tested under 2.6.0, but should work in others.
//
//	Description:  Copies one directory contents to another, 
//		creating the destination directory if it does not exist.  I'm sure
//		there might be better ways to do this, but this should work.
//
//  Resources:  Original discussion at:
//		http://wxforum.shadonet.com/viewtopic.php?t=1833
// 
//  Example Usage:  
//
//		CopyDir("C:\\dev\\test", "c:\\devCopy\\testCopy");
// =================================================================
bool CopyDir(wxString from, wxString to) {

	// set up our proper directory slash character.  If running on
	// windows, __WXMSW__ should be defined in the preprocessor definitions!
	// this is just how i handle slashes. anyone know a more efficient way?
	#ifdef __WXMSW__
		wxString SLASH = "\\";
	#else
		wxString SLASH = "/";
	#endif

	// append a slash if there is not one (for easier parsing)
	// because who knows what people will pass to the function.
	if (to[to.length()-1] != SLASH) {
		to += SLASH;	
	}
	// for both dirs
	if (from[from.length()-1] != SLASH) {
		from += SLASH;	
	}

	// first make sure that the source dir exists
	if(!wxDir::Exists(from)) {
		wxLogError(from + " does not exist.  Can not copy directory.");
	}
	else {
		// check on the destination dir
		// if it doesn't exist...
		if(!wxDir::Exists(to)) {
			// if it doesn't get created
			if(!wxFileName::Mkdir(to, 0777, wxPATH_MKDIR_FULL)) {
				// Send an error
				wxLogError(to + " could not be created.");
				// And exit gracefully
				return false;
			}
		}

		// The directories to traverse
		wxArrayString myDirs;
		// Initially we want one pass
		myDirs.Add("");
		
		// loop through each directory.. storing all sub directories
		// and copying over all files.. the final iteration of one loop
		// should begin an iteration for any subdirectories discovered
		// on the previous pass
		// (rather than pragma, unsigned int will shut the MS compiler up)
		for (unsigned int i = 0; i < myDirs.size(); i++) {

			// get the next directory
			wxDir nextDir(from + myDirs[i]);

			// check that it exists in destination form
			if(!wxDir::Exists(to + myDirs[i])) {
				// if it doesn't, then create it
				if(!wxFileName::Mkdir(to + myDirs[i], 0777, wxPATH_MKDIR_FULL)) {
					// If it doesn't create, error
					wxLogError(to + myDirs[i] + " could not be created.");
					// And exit gracefully
					return false;
				}
			}

			// get the first file in the next directory
			wxString nextFile;
			bool process = nextDir.GetFirst(&nextFile);

			// and while there are still files to process
			while (process) {

				// If this file is a directory
				if(wxDir::Exists(from+nextFile)) {
					// then append it for creation/copying
					myDirs.Add(nextFile + SLASH);	// only add the difference
				}
				else {

					// otherwise just go ahead and copy the file over
					if(!wxCopyFile(from + myDirs[i] + nextFile, 
								   to   + myDirs[i] + nextFile)) {
						// error if we couldn't
						wxLogError("Could not copy " +
							from + myDirs[i] + nextFile + " to "
							+ to + myDirs[i] + nextFile);
					}
				}
				// and get the next file
				process = nextDir.GetNext(&nextFile);
			}

		}
	
		return true;
	}

	return false;
}
// =================================================================

Posted: Fri Apr 29, 2005 7:05 am
by Jorg
Very nice. But for your information, you don't have to define the slash character to be appended. You can use wxFileName and call AppendDir to append a directory name, where the slash is taken care for on the proper OS :-)

But it is a very useful piece of code indeed..

Regards,
- Jorgen

Posted: Fri Apr 29, 2005 3:23 pm
by Tyler
Hey Jorg,

Thanks. I will edit it some time to use wxFileName::AppendDir. I don't like relying on preprocessor definititions necessarily.

-Tyler

Re: Copying a Directory

Posted: Tue May 17, 2005 4:47 pm
by RyanAlt
Tyler wrote: // set up our proper directory slash character. If running on
// windows, __WXMSW__ should be defined in the preprocessor definitions!
// this is just how i handle slashes. anyone know a more efficient way?
#ifdef __WXMSW__
wxString SLASH = "";
#else
wxString SLASH = "/";
#endif
wxFILE_SEP_PATH

Posted: Tue May 17, 2005 8:17 pm
by goeba
Hi,

I

Posted: Tue May 17, 2005 8:37 pm
by Avi
Instead of using a do-while loop for recursion... you might want the function to call itself every time it reaches a subfolder... ;)

Posted: Wed May 18, 2005 5:38 am
by goeba
That

Posted: Wed May 18, 2005 5:58 pm
by Tyler
RyanAlt wrote:wxFILE_SEP_PATH
Ok, now that is cool. :!: I always have a hard time digging up these details, so thanks for providing that. That's a much more elegant solution.
goeba wrote:Hi,

I

Posted: Wed May 18, 2005 6:43 pm
by Avi
[quote="goeba"]That

link to source?

Posted: Fri Apr 07, 2006 9:04 pm
by MoonKid
Is there a link to the source files? Can I use it? What is about the licencs?

Why is it not in the official wxWidgets?

Posted: Sun Jul 15, 2007 3:16 am
by Mr.shi
if ( ! wxEndsWithPathSeparator( to ) )
{
to += wxFILE_SEP_PATH;
}

if ( ! wxEndsWithPathSeparator( from ) )
{
from += wxFILE_SEP_PATH;
}

Posted: Thu Oct 02, 2008 10:45 pm
by Dark Alchemist
Did this function ever get incorporated into WxWidgets?

The only typo I saw was (due to the forum removing one back slash)

Code: Select all

    #ifdef __WXMSW__
            wxString SLASH = "\\";
    #else
            wxString SLASH = "/";
    #endif 
it should read

Code: Select all

    #ifdef __WXMSW__
            wxString SLASH = "\\\";
    #else
            wxString SLASH = "/";
    #endif 
but beyond that it works and would be wonderful if added into WxWidgets (if it hasn't been already).

Re: Copying a Directory

Posted: Thu Dec 15, 2011 2:43 pm
by SandyHip
I have solved to write recursive function copying catalogue

Code: Select all

bool wxCopyDir(wxString sFrom, wxString sTo)
{
    if (sFrom[sFrom.Len() - 1] != '\\' && sFrom[sFrom.Len() - 1] != '/') sFrom += wxFILE_SEP_PATH;
    if (sTo[sTo.Len() - 1] != '\\' && sTo[sTo.Len() - 1] != '/') sTo += wxFILE_SEP_PATH;

    if (!::wxDirExists(sFrom)) {
        ::wxLogError(wxT("%s does not exist!\r\nCan not copy directory"), sFrom.c_str());
        return false;
    }
    if (!wxDirExists(sTo)) {
        if (!wxFileName::Mkdir(sTo, 0777, wxPATH_MKDIR_FULL)) {
            ::wxLogError(wxT("%s could not be created!"), sTo.c_str());
            return false;
        }
    }

    wxDir fDir(sFrom);
    wxString sNext = wxEmptyString;
    bool bIsFile = fDir.GetFirst(&sNext);
    while (bIsFile) {
        const wxString sFileFrom = sFrom + sNext;
        const wxString sFileTo = sTo + sNext;
        if (::wxDirExists(sFileFrom)) {
            wxCopyDir(sFileFrom, sFileTo);
        }
        else {
            if (!::wxFileExists(sFileTo)) {
                if (!::wxCopyFile(sFileFrom, sFileTo)) {
                    ::wxLogError(wxT("Could not copy %s to %s !"), sFileFrom.c_str(), sFileTo.c_str());
                    return false;
                }
            }
        }
        bIsFile = fDir.GetNext(&sNext);
    }
    return true;
}

Re: Copying a Directory

Posted: Wed Feb 01, 2012 11:10 pm
by wx0Pal
Hello,

I wonder why newly created directories have to have "0777" access rights ? Isn't it potentially dangerous, from the security point of view ? Not to mention that it wouldn't work if the target directory has more restricted access right requirements than the process that tries to copy it.

I would propose to copy access control list from the target directory rather than forcing it to be fully accessible.

By the way, +1 for recursive approach proposal.

Regards

Re: Copying a Directory

Posted: Sat Feb 11, 2017 7:32 pm
by Nucleorion
What libraries are needed?