Copying a Directory

If you have a cool piece of software to share, but you are not hosting it officially yet, please dump it in here. If you have code snippets that are useful, please donate!
Tyler
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 246
Joined: Fri Sep 03, 2004 12:37 am
Contact:

Copying a Directory

Post 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;
}
// =================================================================
Last edited by Tyler on Fri Apr 29, 2005 3:31 pm, edited 1 time in total.
Jorg
Moderator
Moderator
Posts: 3971
Joined: Fri Aug 27, 2004 9:38 pm
Location: Delft, Netherlands
Contact:

Post 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
Forensic Software Engineer
Netherlands Forensic Insitute
http://english.forensischinstituut.nl/
-------------------------------------
Jorg's WasteBucket
http://www.xs4all.nl/~jorgb/wb
Tyler
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 246
Joined: Fri Sep 03, 2004 12:37 am
Contact:

Post 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
RyanAlt
In need of some credit
In need of some credit
Posts: 6
Joined: Tue May 03, 2005 8:49 am

Re: Copying a Directory

Post 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
I got voted off the wxIsland!
goeba
Earned a small fee
Earned a small fee
Posts: 21
Joined: Tue May 17, 2005 8:13 pm

Post by goeba »

Hi,

I
Avi
Super wx Problem Solver
Super wx Problem Solver
Posts: 398
Joined: Mon Aug 30, 2004 9:27 pm
Location: Tel-Aviv, Israel

Post 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... ;)
goeba
Earned a small fee
Earned a small fee
Posts: 21
Joined: Tue May 17, 2005 8:13 pm

Post by goeba »

That
Tyler
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 246
Joined: Fri Sep 03, 2004 12:37 am
Contact:

Post 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
Avi
Super wx Problem Solver
Super wx Problem Solver
Posts: 398
Joined: Mon Aug 30, 2004 9:27 pm
Location: Tel-Aviv, Israel

Post by Avi »

[quote="goeba"]That
MoonKid
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 543
Joined: Wed Apr 05, 2006 9:39 am
Contact:

link to source?

Post 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?
Mr.shi
Earned a small fee
Earned a small fee
Posts: 13
Joined: Fri Jul 13, 2007 3:05 am

Post by Mr.shi »

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

if ( ! wxEndsWithPathSeparator( from ) )
{
from += wxFILE_SEP_PATH;
}
Dark Alchemist
Super wx Problem Solver
Super wx Problem Solver
Posts: 347
Joined: Wed Nov 02, 2005 10:33 am

Post 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).
SandyHip
Earned a small fee
Earned a small fee
Posts: 11
Joined: Wed Jun 02, 2010 9:44 am

Re: Copying a Directory

Post 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;
}
wx0Pal
In need of some credit
In need of some credit
Posts: 2
Joined: Wed Feb 01, 2012 8:07 pm
Contact:

Re: Copying a Directory

Post 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
User avatar
Nucleorion
Knows some wx things
Knows some wx things
Posts: 45
Joined: Sat Jan 07, 2017 10:08 pm

Re: Copying a Directory

Post by Nucleorion »

What libraries are needed?
Post Reply