使用Qt复制目录

使用Qt复制目录,qt,qt4,directory-traversal,Qt,Qt4,Directory Traversal,我想将目录从一个驱动器复制到另一个驱动器。我选择的目录包含许多子目录和文件 如何使用Qt实现同样的功能?困难的方法。单独复制每个文件 使用QDir::entryList()迭代目录的内容 使用QDir::cd()和QDir::cdUp()进出目录 使用QDir::mkdir()和QDir::mkpath()创建新文件夹树 最后,使用QFile::copy()复制实际文件 您可以手动执行以下操作: 1) 。使用下面的func,可以生成文件夹/文件列表(递归)-目标文件 static void r

我想将目录从一个驱动器复制到另一个驱动器。我选择的目录包含许多子目录和文件


如何使用Qt实现同样的功能?

困难的方法。单独复制每个文件

  • 使用
    QDir::entryList()
    迭代目录的内容
  • 使用
    QDir::cd()
    QDir::cdUp()
    进出目录
  • 使用
    QDir::mkdir()
    QDir::mkpath()
    创建新文件夹树
  • 最后,使用
    QFile::copy()
    复制实际文件

您可以手动执行以下操作:

1) 。使用下面的func,可以生成文件夹/文件列表(递归)-目标文件

static void recurseAddDir(QDir d, QStringList & list) {

    QStringList qsl = d.entryList(QDir::NoDotAndDotDot | QDir::Dirs | QDir::Files);

    foreach (QString file, qsl) {

        QFileInfo finfo(QString("%1/%2").arg(d.path()).arg(file));

        if (finfo.isSymLink())
            return;

        if (finfo.isDir()) {

            QString dirname = finfo.fileName();
            QDir sd(finfo.filePath());

            recurseAddDir(sd, list);

        } else
            list << QDir::toNativeSeparators(finfo.filePath());
    }
}
static void recurseaddir(QDir d、QStringList&list){
QStringList qsl=d.entryList(QDir::NoDotAndDotDot | QDir::Dirs | QDir::Files);
foreach(QString文件,qsl){
QFileInfo-finfo(QString(“%1/%2”).arg(d.path()).arg(文件));
if(finfo.isSymLink())
返回;
if(finfo.isDir()){
QString dirname=finfo.fileName();
QDir-sd(finfo.filePath());
递归读写器(sd,列表);
}否则
列表isConsole)?tr(“制作Alta GTD的副本”):“”)
.arg(i+1)
.arg(gtdStringList.count());
qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
如果(progressDialog.wasCancelled()){
//删除tmp文件/文件夹
rmDirectoryRecursive(tmpFolder);
rmDirectoryRecursive(tmpFolderPlus);
setEnableGUI(true);
返回;
}
//应付
if(!QFile::copy(gtdStringList.at(i)、tmpStringList.at(i))){
如果(警告标志){
QMessageBox框(此);
QString name=tr(“问题”);
QString file1=getShortName(gtdStringList.at(i),QString(“\\…\”);
QString file2=getShortName(tmpStringList.at(i),QString(“\\…\”);
QString text=tr(“无法将%1复制到%2”\
此文件将被忽略,只需按“是”按钮\
“按YesToAll按钮可自动忽略其他警告…”\
“或按Abort取消操作”).arg(文件1).arg(文件2);
box.setModal(true);
box.setWindowTitle(名称);
box.setText(QString::fromLatin1(“%1”).arg(text));
setIcon(QMessageBox::Question);
设置标准按钮(QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::Abort);
开关(box.exec()){
案例(QMessageBox::YesToAll):
警告标志=错误;
打破
案例(QMessageBox::是):
打破
案例(QMessageBox::中止):
rmDirectoryRecursive(tmpFolder);
rmDirectoryRecursive(tmpFolderPlus);
setEnableGUI(true);
返回;
}
}
}
}

仅此而已。祝你好运!

我想要类似的东西,而且还在谷歌上搜索(徒劳),所以我必须:

static bool cpDir(const QString &srcPath, const QString &dstPath)
{
    rmDir(dstPath);
    QDir parentDstDir(QFileInfo(dstPath).path());
    if (!parentDstDir.mkdir(QFileInfo(dstPath).fileName()))
        return false;

    QDir srcDir(srcPath);
    foreach(const QFileInfo &info, srcDir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) {
        QString srcItemPath = srcPath + "/" + info.fileName();
        QString dstItemPath = dstPath + "/" + info.fileName();
        if (info.isDir()) {
            if (!cpDir(srcItemPath, dstItemPath)) {
                return false;
            }
        } else if (info.isFile()) {
            if (!QFile::copy(srcItemPath, dstItemPath)) {
                return false;
            }
        } else {
            qDebug() << "Unhandled item" << info.filePath() << "in cpDir";
        }
    }
    return true;
}
这不处理链接和特殊文件,顺便说一句。

这基本上是一个轻微的变化,因为它在Qt5.6中对我来说是中断的(这是最热门的问题),所以所有的功劳都归我所有

void copyPath(QString src, QString dst)
{
    QDir dir(src);
    if (! dir.exists())
        return;

    foreach (QString d, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
        QString dst_path = dst + QDir::separator() + d;
        dir.mkpath(dst_path);
        copyPath(src+ QDir::separator() + d, dst_path);
    }

    foreach (QString f, dir.entryList(QDir::Files)) {
        QFile::copy(src + QDir::separator() + f, dst + QDir::separator() + f);
    }
}
功能

bool copyPath(QString sourceDir, QString destinationDir, bool overWriteDirectory)
{
    QDir originDirectory(sourceDir);

    if (! originDirectory.exists())
    {
        return false;
    }

    QDir destinationDirectory(destinationDir);

    if(destinationDirectory.exists() && !overWriteDirectory)
    {
        return false;
    }
    else if(destinationDirectory.exists() && overWriteDirectory)
    {
        destinationDirectory.removeRecursively();
    }

    originDirectory.mkpath(destinationDir);

    foreach (QString directoryName, originDirectory.entryList(QDir::Dirs | \
                                                              QDir::NoDotAndDotDot))
    {
        QString destinationPath = destinationDir + "/" + directoryName;
        originDirectory.mkpath(destinationPath);
        copyPath(sourceDir + "/" + directoryName, destinationPath, overWriteDirectory);
    }

    foreach (QString fileName, originDirectory.entryList(QDir::Files))
    {
        QFile::copy(sourceDir + "/" + fileName, destinationDir + "/" + fileName);
    }

    /*! Possible race-condition mitigation? */
    QDir finalDestination(destinationDir);
    finalDestination.refresh();

    if(finalDestination.exists())
    {
        return true;
    }

    return false;
}
/*! Overwrite existing directories. */
bool directoryCopied = copyPath(sourceDirectory, destinationDirectory, true);

/*! Do not overwrite existing directories. */
bool directoryCopied = copyPath(sourceDirectory, destinationDirectory, false);
使用:

bool copyPath(QString sourceDir, QString destinationDir, bool overWriteDirectory)
{
    QDir originDirectory(sourceDir);

    if (! originDirectory.exists())
    {
        return false;
    }

    QDir destinationDirectory(destinationDir);

    if(destinationDirectory.exists() && !overWriteDirectory)
    {
        return false;
    }
    else if(destinationDirectory.exists() && overWriteDirectory)
    {
        destinationDirectory.removeRecursively();
    }

    originDirectory.mkpath(destinationDir);

    foreach (QString directoryName, originDirectory.entryList(QDir::Dirs | \
                                                              QDir::NoDotAndDotDot))
    {
        QString destinationPath = destinationDir + "/" + directoryName;
        originDirectory.mkpath(destinationPath);
        copyPath(sourceDir + "/" + directoryName, destinationPath, overWriteDirectory);
    }

    foreach (QString fileName, originDirectory.entryList(QDir::Files))
    {
        QFile::copy(sourceDir + "/" + fileName, destinationDir + "/" + fileName);
    }

    /*! Possible race-condition mitigation? */
    QDir finalDestination(destinationDir);
    finalDestination.refresh();

    if(finalDestination.exists())
    {
        return true;
    }

    return false;
}
/*! Overwrite existing directories. */
bool directoryCopied = copyPath(sourceDirectory, destinationDirectory, true);

/*! Do not overwrite existing directories. */
bool directoryCopied = copyPath(sourceDirectory, destinationDirectory, false);
试试这个:

bool copyDirectoryFiles(const QString &fromDir, const QString &toDir, bool coverFileIfExist)
{
    QDir sourceDir(fromDir);
    QDir targetDir(toDir);
    if(!targetDir.exists()){    /* if directory don't exists, build it */
        if(!targetDir.mkdir(targetDir.absolutePath()))
            return false;
    }

    QFileInfoList fileInfoList = sourceDir.entryInfoList();
    foreach(QFileInfo fileInfo, fileInfoList){
        if(fileInfo.fileName() == "." || fileInfo.fileName() == "..")
            continue;

        if(fileInfo.isDir()){    /* if it is directory, copy recursively*/
            if(!copyDirectoryFiles(fileInfo.filePath(),  
                targetDir.filePath(fileInfo.fileName()), 
                coverFileIfExist)) 
                return false;
        }
        else{            /* if coverFileIfExist == true, remove old file first */
            if(coverFileIfExist && targetDir.exists(fileInfo.fileName())){
                targetDir.remove(fileInfo.fileName());
            }

            // files copy
            if(!QFile::copy(fileInfo.filePath(),  
                targetDir.filePath(fileInfo.fileName()))){ 
                    return false;
            }
        }
    }
    return true;
}

我制作了一个库,通过shell命令风格的API来操作文件。它支持文件的递归副本,并处理了更多的条件

范例

cp(“-a”,“://*”,“/target”);//递归地将所有文件从qrc资源复制到目标路径
cp(“tmp.txt”,即“/tmp”);
cp(“*.txt”,“/tmp”);
cp(“/tmp/123.txt”、“456.txt”);
cp(“-va”、“src/*”、“/tmp”);
cp(“-a”,”:resource“,“/target”);

由于我在macOS上使用应用程序捆绑包时遇到了一些问题,这里有一个使用QDirIterator的解决方案

void copyAndReplaceFolderContents(const QString &fromDir, const QString &toDir, bool copyAndRemove = false) {
QDirIterator it(fromDir, QDirIterator::Subdirectories);
QDir dir(fromDir);
const int absSourcePathLength = dir.absoluteFilePath(fromDir).length();

while (it.hasNext()){
    it.next();
    const auto fileInfo = it.fileInfo();
    if(!fileInfo.isHidden()) { //filters dot and dotdot
        const QString subPathStructure = fileInfo.absoluteFilePath().mid(absSourcePathLength);
        const QString constructedAbsolutePath = toDir + subPathStructure;
        
        if(fileInfo.isDir()){
            //Create directory in target folder
            dir.mkpath(constructedAbsolutePath);
        } else if(fileInfo.isFile()) {
            //Copy File to target directory

            //Remove file at target location, if it exists. Otherwise QFile::copy will fail
            QFile::remove(constructedAbsolutePath);
            QFile::copy(fileInfo.absoluteFilePath(), constructedAbsolutePath);
        }
    }
}

if(copyAndRemove)
    dir.removeRecursively();

}

我试着将我的更正作为编辑发布,但似乎没有人理解,所以我将在这里发布。使用
QString(“%1/%2”).arg(d.path()).arg(file)
通常不是一个好主意,因为可以在文件或路径名中找到“%1”或“%2”(在大多数文件系统中)。以cygwin创建的此路径为例
c:\cyg\ftp%3a%2f%2fcygwin.mirrorcatalogs.com%2fcygwin%2f
。假设这是
d.path()
中保存的内容,并且
文件具有
text.txt
”1'将替换为
d.path()
以形成
c:\cyg\ftp%3a%2f%2fcygwin.mirrorcalogs.com%2fcygwin%2f/%2
。最后,您将拥有
c:\cyg\ftp%3atext.txtftext.txtfcygwin.mirrorcalogs.comtext.txtfcygwintext.txtf/text.txt
。一个更好的选择是
d.path().append('/').append(file)
如果使用append,它将返回一个引用,如果在其他地方再次使用它,它可能会更改。如果需要,请小心安全的替代方法是
QString(“%1/%2”).arg(d.path(),file)
-但最好使用
d.filePath(file)组合路径名
可移植地使用平台的目录分隔符。当然,您仍然需要
QString::arg(QString,QString)
来编写消息框文本。我不知道这是我的装备还是Qt5.6中的这段代码,但这段代码似乎挂起了。它正在进行目录复制,但从未完成。奇怪,嗯,是的。第一次复制操作正常,然后后续的复制就开始失控。创建一个目录,然后将该目录复制到子目录中。第一个有效,第二个,砰,死了。谢谢你的代码片段,它可能会提供一些即时的帮助。通过说明为什么这是一个很好的解决问题的方法,正确地解释它的教育价值,并将使它对未来有类似但不完全相同问题的读者更有用。请在回答中添加解释,并说明适用的限制和假设。有什么不同,为什么不同?