Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

walk a directory while ziping the directory



  • I am trying to walk a directory the user selects the directory and zip file name. When I go to add the filepath of the directory and the file name it adds the entire file path..

    example:

    "C:\Users\1\Desktop\2\3\release\4\5\Numbers"

    I am trying to append the last folder name while walking the directory.

    CODE:

    void MainWindow::saveFile()
    {
        QString existingDirectory = QFileDialog::getExistingDirectory(0, ("Select Zip Folder"),QDir::currentPath());
    	QString zipFileName = QFileDialog::getSaveFileName(this, tr("Save Zip File Name"), "", tr("Zip Files (*.zip)"));
    	
    	qint32 err = 0;
        struct zip *packZip = zip_open(zipName.toLatin1().constData(), ZIP_CREATE | ZIP_EXCL, &err);
        if (!packZip)
        {
            zip_error_t error;
            zip_error_init_with_code(&error, err);
            QMessageBox::warning(nullptr, "",QString("Can't pack open packed zip file %1 with error %2 and err_code %3").arg(zipFileName, zip_error_strerror(&error)).arg(err));
            zip_error_fini(&error);
            return false;
        }
    
        walkDirectory(existingDirectory, packZip);
        zip_close(packZip);
    }
    
    void MainWindow::walkDirectory( const QString& sDir, struct zip *packZip)
    {
        QDir dir(sDir);
        dir.setCurrent(sDir);
        QFileInfoList list = dir.entryInfoList();
        for (int iList=0;iList<list.count();iList++)
        {
            QFileInfo info = list[iList];
            QString sFilePath = info.filePath();
            if (info.isDir())
            {
                // recursive
                if (info.fileName()!=".." && info.fileName()!=".")
                {
                    if (zip_dir_add(packZip, sFilePath.toLatin1().constData(), ZIP_FL_ENC_UTF_8) < 0)
                    {
                        QMessageBox::warning(nullptr, "",QString("Failed to add packed directory to zip"));
    					return;
                    }
                    qDebug() << "sFilePath" << sFilePath;
                    walkDirectory(sFilePath, packZip);
                }
            }
            else
            {
                zip_source_t *source = zip_source_file(packZip, sFilePath.toLatin1().constData(), 0, 0);
                if (source == nullptr)
                {
                    QMessageBox::warning(nullptr, "",QString("Failed to add packed file to zip source"));
                    return;
                }
                if (zip_file_add(packZip, sFilePath.toLatin1().constData(), source, ZIP_FL_ENC_UTF_8) < 0)
                {
                    zip_source_free(source);
                    QMessageBox::warning(nullptr, "",QString("Failed to add packed file to zip"));
                    return;
                }
            }
        }
    }
    

    The code works but it adds the entire file path rather than the selected folder name and the rest going forward.

    also how would i add say ../qt/books the "../" in the path?


  • Moderators

    @Styx said in walk a directory while ziping the directory:

    QString sFilePath = info.filePath();

    Change this to:

    QString sFilePath = info.filename();
    


  • The method you suggested didn't work. It should be copying the folder name to the zip directory but it doesn't.

    /numbers
    /numbers/1/file1
    /numbers/2/2/file2
    /numbers/3/3/file3
    etc...



  • @Styx It is not clear whether your last post show what you get, or what you expect to get.

    If your user gives you directory "C:\Users\1\Desktop\2\3\release\4\5\Numbers" you will not get the "numbers" part of the path because you start your recursion inside that folder. That is fairly easily fixed.

    To get a relative path to each file, you will have to either build it as you recurse or derive it by using QDir::relativeFilePath() on the QDir object representing the top of the tree with the full path to each file.

    Something like this with a good sprinkling of sanity and error checks (handling for sym links etc. too)

    #include <QCoreApplication>
    #include <QDir>
    #include <QDebug>
    
    void walkDirectory(const QString& sDir)
    {
        QDir d(sDir);
        QFileInfoList entries = d.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot, QDir::Name);
        foreach (QFileInfo entry, entries) {
            if (entry.isDir()) {
                qDebug() << "Adding directory" << sDir + "/" + entry.fileName();
                walkDirectory(sDir + "/" + entry.fileName());
            }
            else {
                qDebug() << "Adding file" << sDir + "/" + entry.fileName();
            }
        }
    }
    
    void recursiveZip(const QString& sDir)
    {
        QString oldPWD = QDir::currentPath();
    
        QDir topDir(sDir);
        QString dirName = topDir.dirName();
        topDir.cdUp();
        QDir::setCurrent(topDir.path());
        walkDirectory(dirName);
    
        QDir::setCurrent(oldPWD);
    }
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
        recursiveZip("/tmp/test/numbers");
        return 0;
    }
    

Log in to reply