PDA

View Full Version : Copy Directory Recusively



hkothari
21st August 2009, 13:40
So I'm writing a function to copy a file or directory recursively, if it's just a file It just uses QFile Copy, and it copies the file and it works, but when it's a directory, I get the directory Entry List and loop through it calling the copy method for each file, for some reason I keep getting put into some endless loop. Can anyone help me out with this? My code is below.

bool copy(QString sourceFilePath, QString destinationFilePath)
{
QFile sourceFile(sourceFilePath);
QFile destinationFile(destinationFilePath);
QFileInfo sourceFileInfo(sourceFile);
QFileInfo destinationFileInfo(destinationFile);

if(sourceFileInfo.fileName() == "." || sourceFileInfo.fileName() == "..")
return true;

//If we're just copying a file and it's already readable.
if(sourceFileInfo.isFile() && sourceFileInfo.isReadable())
{
if(destinationFileInfo.isFile() && destinationFile.isWritable())
{
//Warning, this deletes the file and replaces it.
QString newFileName = destinationFile.fileName();
destinationFile.remove();
return sourceFile.copy(newFileName);
}
else if(destinationFileInfo.isDir() && destinationFileInfo.isWritable())
{
//We can use fileName in this case because we know that the FULL PATH is set above.
QString newFileName = destinationFile.fileName();
newFileName.append("/");
//We have to use this to get JUST THE FILE NAME of the original file.
newFileName.append(QFileInfo(sourceFile).fileName( ));
return sourceFile.copy(newFileName);
}
}
//If we're copying a directory, it'll have to be done recursively.
else if(sourceFileInfo.isDir() && sourceFileInfo.isReadable())
{
qDebug() << "SFI Abs Path:" << sourceFileInfo.absolutePath();
QDir sourceFileDir(sourceFileInfo.absolutePath());
sourceFileDir.setFilter(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot | QDir::Readable);
QDir destinationFileDir(destinationFileInfo.absolutePat h());
qDebug() << "Mkdir output" << destinationFileDir.mkdir(sourceFileInfo.baseName() );
destinationFileDir.cd(sourceFileInfo.baseName());

const QFileInfoList sourceFileDirInfoList = sourceFileDir.entryInfoList();
for(int i = 0; i < sourceFileDirInfoList.size(); i++)
{
qDebug() << "Copy params: " << sourceFileDirInfoList[i].absoluteFilePath() << destinationFileDir.absolutePath();
copy(sourceFileDirInfoList[i].absoluteFilePath(), destinationFileDir.absolutePath());
}

return true;
}

//If we end up here, something went wrong.
return false;
}

yogeshgokul
21st August 2009, 13:46
Use this function:

void copyFolder(QString sourceFolder, QString destFolder)
{
QDir sourceDir(sourceFolder);
if(!sourceDir.exists())
return;
QDir destDir(destFolder);
if(!destDir.exists())
{
destDir.mkdir(destFolder);
}
QStringList files = sourceDir.entryList(QDir::Files);
for(int i = 0; i< files.count(); i++)
{
QString srcName = sourceFolder + "/" + files[i];
QString destName = destFolder + "/" + files[i];
QFile::copy(srcName, destName);
}
files.clear();
files = sourceDir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
for(int i = 0; i< files.count(); i++)
{
QString srcName = sourceFolder + "/" + files[i];
QString destName = destFolder + "/" + files[i];
copyFolder(srcName, destName);
}
}

hkothari
21st August 2009, 13:51
Thank you very much, that seems to work.

numbat
22nd August 2009, 12:34
Here's a way to do it with iteration rather than recursion. None of these solutions avoid the infinite recursion (http://blogs.msdn.com/oldnewthing/archive/2004/12/27/332704.aspx) problem.



void copyFolder(const QString& sourceFolder,const QString& destFolder)
{
QQueue< QPair<QString, QString> > queue;

queue.enqueue(qMakePair(sourceFolder, destFolder));

while (!queue.isEmpty())
{
QPair<QString, QString> pair = queue.dequeue();
QDir sourceDir(pair.first);
QDir destDir(pair.second);

if(!sourceDir.exists())
continue;

if(!destDir.exists())
destDir.mkpath(pair.second);

QStringList files = sourceDir.entryList(QDir::Files);
for(int i = 0; i < files.count(); i++)
{
QString srcName = pair.first + "/" + files.at(i);
QString destName = pair.second + "/" + files.at(i);
QFile::copy(srcName, destName);
}

QStringList dirs = sourceDir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
for(int i = 0; i < dirs.count(); i++)
{
QString srcName = pair.first + "/" + dirs.at(i);
QString destName = pair.second + "/" + dirs.at(i);
queue.enqueue(qMakePair(srcName, destName));
}
}
}

Lykurg
22nd August 2009, 12:43
I'd prefer recursive calling instead of cashing the paths in a queue, but anyway, use QDir::separator() instead of the slash in case you want cross platform compatibility.