Copy Directory Recusively
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.
Code:
{
QFile sourceFile
(sourceFilePath
);
QFile destinationFile
(destinationFilePath
);
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.
absolutePath());
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;
}
Re: Copy Directory Recusively
Use this function:
Code:
{
QDir sourceDir
(sourceFolder
);
if(!sourceDir.exists())
return;
QDir destDir
(destFolder
);
if(!destDir.exists())
{
destDir.mkdir(destFolder);
}
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);
}
}
Re: Copy Directory Recusively
Thank you very much, that seems to work.
Re: Copy Directory Recusively
Here's a way to do it with iteration rather than recursion. None of these solutions avoid the infinite recursion problem.
Code:
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);
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
);
}
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));
}
}
}
Re: Copy Directory Recusively
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.