2010-03-29 13 views

Odpowiedz

6

Trudna droga. Skopiuj każdy plik indywidualnie.

  • Zastosowanie QDir::entryList() iteracyjne nad zawartością katalogu
  • Korzystanie QDir::cd() i QDir::cdUp() aby wchodzić i wychodzić z katalogów
  • Korzystając QDir::mkdir() i QDir::mkpath() do tworzenia nowych folderów drzewo
  • i wreszcie stosowanie QFile::copy() do kopiowania rzeczywistych plików
12

Ręcznie, możesz wykonać następujące czynności:

1). z func poniżej generujesz listę folderów/plików (rekursywnie) - pliki docelowe.

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). Następnie można rozpocząć kopiowanie plików z przeznaczenia listy do nowego katalogu źródłowego tak:

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

I to wszystko. Powodzenia!

+1

Próbowałem opublikowania mojego sprostowania jako edit ale nikt nie wydaje się go zrozumieć, więc będę je zamieszczać tutaj. przy użyciu 'QString ("% 1 /% 2 ") arg (d.path()). arg (plik)' nie jest dobrym pomysłem, ponieważ "% 1" lub "% 2" można znaleźć (w większości systemy plików) w pliku lub ścieżce. weź tę ścieżkę stworzoną przez cygwin jako przykład 'c: \ cyg \ ftp% 3a% 2f% 2fcygwin.mirrorcatalogs.com% 2fcygwin% 2f'. – vikki

+3

Powiedzmy, że to jest to, co jest przechowywane w 'd.path()' a 'file' ma' text.txt'. "% 1" zostanie zastąpione przez 'd.path()', aby utworzyć 'c: \ cyg \ ftp% 3a% 2f% 2fcygwin.mirrorcatalogs.com% 2fcygwin% 2f /% 2'. na końcu będziesz miał 'c: \ cyg \ ftp% 3atext.txtftext.txtfcygwin.mirrorcatalogs.comtext.txtfcygwintext.txtf/text.txt'. lepszą opcją jest 'd.path(). append ('/'). append (file)' – vikki

+0

@vikki: Tak! Masz rację! – mosg

5

chciałem coś podobnego i został googlowania (bezskutecznie), więc jest to gdzie mam się:

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

Używa rmDir funkcję, która wygląda dość podobne:

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

To nie obsługuje linków i plików specjalnych, btw.

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

Nie wiem, czy to moje urządzenie, czy ten kod w Qt 5.6, ale ten kod wydaje się zawieszać. Robi kopiowanie katalogów, ale nigdy nie kończy. Dziwne. –

+0

Hm, tak. Pierwsza operacja kopiowania działa, a kolejne kopie idą bananami. Zrób katalog, a następnie skopiuj ten katalog do podkatalogu. Pierwsze prace, drugie, bang, martwe. –

0

Jest to w zasadzie petch's answer z niewielką zmianą ze względu na jego zerwania dla mnie w Qt 5.6 (jest to górna pytanie hit), więc wszystko zasługa petch.

funkcja

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

Zastosowanie:

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

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

Co jest innego i dlaczego? –

1

Spróbuj tego:

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

Dziękujemy za ten fragment kodu, który może zapewnić natychmiastową pomoc. Właściwe wyjaśnienie [znacznie się poprawi] (// meta.stackexchange.com/q/114762) jego wartość edukacyjna poprzez pokazanie * dlaczego * jest to dobre rozwiązanie problemu i sprawiłoby, że byłoby ono bardziej użyteczne dla przyszłych czytelników z podobnymi, ale nie identyczne, pytania. Proszę [edytuj] swoją odpowiedź, aby dodać wyjaśnienie i podać, jakie ograniczenia i założenia mają zastosowanie. –

1

Zrobiłem bibliotekę do operacji na plikach przez shell stylu poleceń API. Obsługuje rekursywną kopię plików i obsługuje kilka innych warunków.

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

Przykład

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