2010-03-29 1 views
18

Я хочу скопировать каталог с одного диска на другой диск. Мой выбранный каталог содержит много подкаталогов и файлов.Копировать каталог с помощью Qt

Как я могу реализовать то же самое с помощью Qt?

ответ

6

Жесткий путь. Скопируйте каждый файл отдельно.

  • Используйте QDir::entryList() перебрать содержимое каталога
  • Используйте QDir::cd() и QDir::cdUp(), чтобы входить и выходить из каталогов
  • Использование QDir::mkdir() и QDir::mkpath() для создания нового дерева каталогов
  • и, наконец, использование QFile::copy() для копирования фактических файлов
12

Вручную можно сделать следующее:

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

И это все. Удачи!

+1

я попытался разместить свою коррекцию как редактировать, но никто, кажется, понимают это, поэтому я выложу его здесь. используя «QString («% 1 /% 2 »). arg (d.path()). arg (file)' обычно не очень хорошая идея, поскольку «% 1» или «% 2» можно найти (в большинстве файловых систем) в имени файла или пути. возьмите этот путь, созданный cygwin в качестве примера 'c: \ cyg \ ftp% 3a% 2f% 2fcygwin.mirrorcatalogs.com% 2fcygwin% 2f'. – vikki

+3

позволяет сказать, что это то, что хранится в 'd.path()' и 'file' имеет' text.txt'. '% 1' будет заменен на 'd.path()', чтобы сформировать 'c: \ cyg \ ftp% 3a% 2f% 2fcygwin.mirrorcatalogs.com% 2fcygwin% 2f /% 2'. наконец, вы получите 'c: \ cyg \ ftp% 3atext.txtftext.txtfcygwin.mirrorcatalogs.comtext.txtfcygwintext.txtf/text.txt'. лучшим вариантом является 'd.path(). append ('/'). append (file)' – vikki

+0

@vikki: Да! Ты прав! – mosg

5

Я хотел что-то подобное, и прибегая к помощи (напрасно), так это то, где я должен:

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

Это не обрабатывает ссылки и специальные файлы, кстати.

11
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

Я не знаю, если это моя установка, или этот код в Qt 5.6, но этот код, кажется, висит. Это делает копирование каталогов, но никогда не заканчивается. Weird. –

+0

Хм, да. Работа первой копии работает, а затем последующие копии идут бананы. Создайте каталог, затем скопируйте этот каталог в поддиректор. Первые работы, во-вторых, удары, мертвые. –

0

Это в основном petch's answer с небольшим изменением в связи с этим нарушения для меня в 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); 
+0

Что поделаешь и почему? –

1

Попробуйте это:

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

Благодарим вас за этот фрагмент кода, который может оказать немедленную помощь. Правильное объяснение [значительно улучшило бы] (// meta.stackexchange.com/q/114762) его образовательное значение, показав * почему * это хорошее решение проблемы и сделало бы его более полезным для будущих читателей с похожими, но не идентичные вопросы. Пожалуйста, отредактируйте свой ответ, чтобы добавить объяснение, и укажите, какие ограничения и допущения применяются. –

1

Я сделал библиотеку для работы с файлами с помощью команды в стиле оболочки 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"); 

 Смежные вопросы

  • Нет связанных вопросов^_^