qt qt4 directory-traversal

Copiar directorio usando Qt



qt4 directory-traversal (7)

El camino difícil. Copia cada archivo individualmente.

  • Use QDir::entryList() para iterar sobre el contenido de un directorio
  • Use QDir::cd() y QDir::cdUp() para entrar y salir de los directorios
  • Use QDir::mkdir() y QDir::mkpath() para crear el nuevo árbol de carpetas
  • y finalmente, use QFile::copy() para copiar los archivos reales

Quiero copiar un directorio de una unidad a otra. Mi directorio seleccionado contiene muchos subdirectorios y archivos.

¿Cómo puedo implementar lo mismo usando Qt?


Esta es básicamente la respuesta de Petch con un ligero cambio debido a que se rompió para mí en Qt 5.6 (esta es la pregunta más importante), por lo que todo el crédito se destina a .

función

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

Utilizar:

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


He creado una biblioteca para manipular archivos mediante una API de estilo de comando de shell. Admite una copia recursiva de archivos y maneja varias condiciones más.

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

Ejemplo

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");


Manualmente, puedes hacer las siguientes cosas:

1). con la función siguiente, genera las carpetas / lista de archivos (recursivamente) - los archivos de destino.

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). luego, puede comenzar a copiar archivos de la lista de destinos en el nuevo directorio de origen:

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

Y eso es todo. ¡Buena suerte!


Prueba esto:

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


Quería algo similar, y estaba buscando en Google (en vano), así que aquí es donde tengo que:

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

Utiliza una función rmDir que se ve bastante 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()); }

Esto no maneja enlaces y archivos especiales, por cierto.


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