2010-03-29 23 views
18

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

¿Cómo puedo implementar lo mismo usando Qt?

Respuesta

6

La manera dura. Copie cada archivo individualmente

  • Uso QDir::entryList() para iterar sobre el contenido de un directorio
  • Uso QDir::cd() y QDir::cdUp() ir dentro y fuera de los directorios
  • Uso QDir::mkdir() y QDir::mkpath() para crear el nuevo árbol de carpetas
  • y, por último, el uso QFile::copy() para copiar los archivos reales
12

Manualmente, puede hacer las siguientes cosas:

1). con la función siguiente genera la lista de carpetas/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). entonces puede empezar a copiar los archivos de la lista de destino al nuevo directorio de origen así:

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!

+1

he intentado publicar mi corrección como una edición pero nadie parece entenderlo, así que voy a publicar aquí. usando 'QString ("% 1 /% 2 "). arg (d.path()). arg (archivo)' generalmente no es una buena idea ya que se puede encontrar '% 1' o '% 2' (en la mayoría sistemas de archivos) en un nombre de archivo o ruta. tome este camino creado por cygwin como un ejemplo 'c: \ cyg \ ftp% 3a% 2f% 2fcygwin.mirrorcatalogs.com% 2fcygwin% 2f'. – vikki

+3

digamos que esto es lo que se mantiene en 'd.path()' y 'file' tiene' text.txt'. '% 1' se reemplazará por 'd.path()' para formar 'c: \ cyg \ ftp% 3a% 2f% 2fcygwin.mirrorcatalogs.com% 2fcygwin% 2f /% 2'. finalmente tendrá 'c: \ cyg \ ftp% 3atext.txtftext.txtfcygwin.mirrorcatalogs.comtext.txtfcygwintext.txtf/text.txt'. una mejor opción es 'd.path(). append ('/'). append (file)' – vikki

+0

@vikki: ¡Sí! ¡Tienes razón! – mosg

5

quería algo similar y se googlear (en vano), por lo 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; 
} 

Se 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.

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

No sé si es mi plataforma, o este código en Qt 5.6, pero este código parece bloquearse. Está haciendo copias de directorio, pero nunca termina. Extraño. –

+0

Hm, sí. La primera operación de copia funciona, y luego las copias siguientes son bananas. Haga un directorio, luego copie ese directorio en un subdirectorio. Primeros trabajos, segundo, bang, muerto. –

0

Esto es básicamente petch's answer con un ligero cambio debido a que se rompa para mí en Qt 5.6 (esta es la pregunta primero éxito), por lo que todo el crédito va a petch.

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

Uso:

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

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

¿Qué es diferente y por qué? –

1

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

Gracias por este fragmento de código, que puede brindar alguna ayuda inmediata. Una explicación adecuada [mejoraría en gran medida] (// meta.stackexchange.com/q/114762) su valor educativo al mostrar * por qué * esta es una buena solución al problema, y ​​lo haría más útil para lectores futuros con similares, pero no idénticas, preguntas. Por favor [edite] su respuesta para agregar una explicación y dar una indicación de qué limitaciones y suposiciones se aplican. –

1

he hecho una biblioteca para manipular archivos de una API estilo comando shell. Es compatible con una copia recursiva de los 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"); 
Cuestiones relacionadas