Copy directory using Qt

前端 未结 7 1240
迷失自我
迷失自我 2020-12-29 05:08

I want to copy a directory from one drive to another drive. My selected directory contains many sub directories and files.

How can I implement the same using Qt?

相关标签:
7条回答
  • 2020-12-29 05:34

    This is basically petch's answer with a slight change due to it breaking for me in Qt 5.6 (this is the top question hit), so all credit goes to petch.

    function

    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;
    }
    

    Use:

    /*! Overwrite existing directories. */
    bool directoryCopied = copyPath(sourceDirectory, destinationDirectory, true);
    
    /*! Do not overwrite existing directories. */
    bool directoryCopied = copyPath(sourceDirectory, destinationDirectory, false);
    
    0 讨论(0)
  • 2020-12-29 05:47

    Manually, you can do the next things:

    1). with func below you generate folders/files list (recursively) - the destination files.

    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());
        }
    }
    

    2). then you may to start copying files from destination list to the new source directory like that:

    for (int i = 0; i < gtdStringList.count(); i++) {
    
        progressDialog.setValue(i);
        progressDialog.setLabelText(tr("%1 Coping file number %2 of %3 ")
            .arg((conf->isConsole) ? tr("Making copy of the Alta-GTD\n") : "")
            .arg(i + 1)
            .arg(gtdStringList.count()));
    
        qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
    
        if (progressDialog.wasCanceled()) {
    
            // removing tmp files/folders
            rmDirectoryRecursive(tmpFolder);
            rmDirectoryRecursive(tmpFolderPlus);
            setEnableGUI(true);
            return;
        }
    
        // coping
        if (!QFile::copy(gtdStringList.at(i), tmpStringList.at(i))) {
    
            if (warningFlag) {
    
                QMessageBox box(this);
                QString name = tr("Question");
                QString file1 = getShortName(gtdStringList.at(i), QString("\\...\\"));
                QString file2 = getShortName(tmpStringList.at(i), QString("\\...\\"));
                QString text = tr("Cannot copy <b>%1</b> <p>to <b>%2</b>"   \
                   "<p>This file will be ignored, just press <b>Yes</b> button" \
                   "<p>Press <b>YesToAll</b> button to ignore other warnings automatically..."  \
                   "<p>Or press <b>Abort</b> to cancel operation").arg(file1).arg(file2);
    
                box.setModal(true);
                box.setWindowTitle(name);
                box.setText(QString::fromLatin1("%1").arg(text));
                box.setIcon(QMessageBox::Question);
                box.setStandardButtons(QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::Abort);
    
                switch (box.exec()) {                   
                    case (QMessageBox::YesToAll):
                        warningFlag = false;
                        break;
                    case (QMessageBox::Yes):
                        break;
                    case (QMessageBox::Abort):
                        rmDirectoryRecursive(tmpFolder);
                        rmDirectoryRecursive(tmpFolderPlus);
                        setEnableGUI(true);
                        return;
                }
            }
        }
    }
    

    And that's all. Good luck!

    0 讨论(0)
  • 2020-12-29 05:48

    I have made a library to manipulate files by a shell command style API. It supports a recursively copy of files and handled several more conditions.

    https://github.com/benlau/qtshell#cp

    Example

    cp("-a", ":/*", "/target"); // copy all files from qrc resource to target path recursively
    
    cp("tmp.txt", "/tmp");
    
    cp("*.txt", "/tmp");
    
    cp("/tmp/123.txt", "456.txt");
    
    cp("-va","src/*", "/tmp");
    
    cp("-a", ":resource","/target");
    
    0 讨论(0)
  • 2020-12-29 05:49

    I wanted something similar, and was googling (in vain), so this is where I've got to:

    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;
    }
    

    It uses an rmDir function that looks pretty similar:

    static bool rmDir(const QString &dirPath)
    {
        QDir dir(dirPath);
        if (!dir.exists())
            return true;
        foreach(const QFileInfo &info, dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) {
            if (info.isDir()) {
                if (!rmDir(info.filePath()))
                    return false;
            } else {
                if (!dir.remove(info.fileName()))
                    return false;
            }
        }
        QDir parentDir(QFileInfo(dirPath).path());
        return parentDir.rmdir(QFileInfo(dirPath).fileName());
    }
    

    This doesn't handle links and special files, btw.

    0 讨论(0)
  • 2020-12-29 05:52

    The hard way. Copy every file individually.

    • Use QDir::entryList() to iterate over the content of a directory
    • Use QDir::cd() and QDir::cdUp() to go in and out of directories
    • Use QDir::mkdir() and QDir::mkpath() to create the new folders tree
    • and finally, use QFile::copy() to copy the actual files
    0 讨论(0)
  • 2020-12-29 05:56
    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);
        }
    }
    
    0 讨论(0)
提交回复
热议问题