Вопрос:
Я хочу скопировать каталог с одного диска на другой диск. Мой выбранный каталог содержит много подкаталогов и файлов.
Как я могу реализовать то же самое с помощью Qt?
Ответ №1void 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); } } Ответ №2
В ручном режиме вы можете сделать следующее:
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()); } }
2). то вы можете начать копирование файлов из списка адресатов в новый исходный каталог следующим образом:
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-GTDn») : «») .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; } } } }
И это все. Удачи!
Ответ №3
Трудный путь. Скопируйте каждый файл отдельно.
- Используйте QDir::entryList() для перебора содержимого каталога
- Используйте QDir::cd() и QDir::cdUp() для входа и выхода из директорий
- Используйте QDir::mkdir() и QDir::mkpath() для создания нового дерева папок
- и, наконец, используйте QFile::copy() для копирования фактических файлов
Ответ №4
Я хотел что-то подобное, и был googling (напрасно), так что вот где я должен:
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; }
Он использует функцию rmDir, которая выглядит довольно похоже:
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()); }
Это не обрабатывает ссылки и специальные файлы, кстати.
Ответ №5
Это в основном ответ petch с небольшим изменением из-за его нарушения для меня в Qt 5.6 (это главный вопрос), поэтому все кредиты идут до petch.
функция
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); Ответ №6
Попробуйте следующее:
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; } Ответ №7
Я создал библиотеку для управления файлами с помощью API-интерфейса оболочки. Он поддерживает рекурсивную копию файлов и обрабатывает еще несколько условий.
https://github.com/benlau/qtshell#cp
Пример
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»);