What is the best way to iterate trough multiple directories to find a file



  • Hi,

    What I'm trying to do is open a PDF file using the user's default program for this type of files. The way I have it now works, but I don't think this is the most efficient way of doing it since I'm using the entryList() function and I'm not sure if this is efficient for the purpose I'm using it .

    This is what I have. When a button is clicked it looks for a fileName.pdf if this returns false it gets a list of folders in that directory and then iterate trough all of them until it finds fileName.pdf, once found it stops iterating.

    @void MainWindow::on_pushButton_clicked()
    {
    bool targetFile = QDesktopServices::openUrl(QUrl("file:///c:/rootFolder/fileName.pdf"));
    if(!targetFile)
    {
    QDir currentDirectory("c:/rootFolder");
    QStringList listOfFolders = currentDirectory.entryList(QDir::Dirs);// get a list of folders

        for(int i=0; i<listOfFolders.count(); i++)
        {
            bool targetFileContinued = QDesktopServices::openUrl(QUrl("file:///c:/rootFolder/"+ listOfFolders.at(i)+"/fileName.pdf"));
            if(targetFileContinued == true)
            {
                break;
            }
        }
    }
    

    }@

    Again, the way I have it works but I have a feeling that this is not what I should be doing in fact I want to go one step deeper (one more directory deeper) if not found in the second attempt which means I will have to get a list of each folder in the first list and iterate trough each folder and so on.

    What is the typical way to iterate though multiple folder when searching for a file?

    FYI
    The URLs are going to be more dynamic than what I show in my code, I just did it like that to show my code.

    Thanks a lot


  • Moderators

    don't use QDesktopServices::openUrl() to check if a file exists.
    QDesktopServices::openUrl() actually tries to open the file with the default view of your system. Meaning like you would double click the file.
    Use QFile::exists() instead.

    Something like this:
    @
    void MainWindow::on_pushButton_clicked()
    {
    QString fileName("fileName.pdf");

      QDir dir("c:/rootFolder");
    
      if( QFile&#40;dir.absoluteFilePath(fileName&#41;).exists() )
      {
           //do something with it
      }
      else
      {
              foreach( QString folder, QcurrentDirectory.entryList(QDir::Dirs) )
              {
                       QFile file = QDir(folder).absoluteFilePath(fileName);
                       if( file.exists() )
                       {
                                  //do something with it
                                 break;
                       }
              }
       }
    

    }
    @



  • Thanks a lot for the improved code.



  • I thought I was going to be able to figure this out, and I kind of did but not exactly how I wanted performance wise.

    The code below does exactly what I wanted to do but it's not as efficient as I wanted it to be. What this code does is basically finds a file with the specified name and opens it in the default application for the type of file, it searches in three folder levels.

    The program starts by searching the root folder if it doesn't find the file there it goes and grabs a list of folders in that folder and searches each one, if the files is not in any of these folders either it goes a folder deeper grabbing a list of folders again and searching each one, and finally it ends there regardless if the file was found or not.

    - Root Folder
    --- Root Folder/Second Folders
    ----- Root Folder/Second Folders / Subfolders

    @void MainWindow::on_pushButton_Find_clicked()
    {
    QString fileName("fileName.pdf");
    QString targetFolder = "c:/rootFolder";
    QString folder;
    QDir mainTargetDirectory(targetFolder);

    if( QFile&#40;mainTargetDirectory.absoluteFilePath(fileName&#41;&#41;.exists(&#41;&#41;
    {
        QDesktopServices::openUrl(QUrl("file:///"+ targetFolder + "/" +fileName));
    }
    else if(!QFile&#40;mainTargetDirectory.absoluteFilePath(fileName&#41;&#41;.exists(&#41;&#41;
    {
        foreach(folder, mainTargetDirectory.entryList(QDir::Dirs) )
        {
            QFile nextFolder (mainTargetDirectory.absoluteFilePath(folder)+ "/"+ fileName);
            if(nextFolder.exists())
            {
                QDesktopServices::openUrl(QUrl("file:///"+ targetFolder + "/" + folder + "/" +fileName));
                break;
            }
            else if(!nextFolder.exists())
            {
               QDir mainTargetDirectoryPlus(targetFolder + "/" + folder);
               foreach( QString folder2, mainTargetDirectoryPlus.entryList(QDir::Dirs) )
               {
                   QFile nextFolder2 (mainTargetDirectoryPlus.absoluteFilePath(folder2)+ "/"+ fileName);
                   if(nextFolder2.exists())
                   {
                       QDesktopServices::openUrl(QUrl("file:///"+ targetFolder + "/" + folder + "/"+folder2+"/" +fileName));
                       break;
                   }
               }
            }
        }
    }
    

    }@

    What I don't like about this code is the fact that if the file is found in the second set of folders it still searches the third set of folders since the second foreach is nested inside the first one, I tried a few things but nothing, I couldn’t find a better way.

    How can I improve the above code? As I said it works fine but I don't want to waste time searching in folders if it I don't have to.

    Any suggestion to improve my poor code?


  • Moderators

    you have the following options:

    on success (file found) you break the loops. For nested loops you can do like "this":http://stackoverflow.com/a/1257760.

    or you create an initial list containing all folders to search and finally use a single loop to iterate

    @
    QStringList dirs = ....;
    foreach( QString directory, directories )
    {
    QFile file = QDir(directory).absoluteFilePath(fileName);
    if( file.exists() )
    {
    //do something with it
    break;
    }
    }
    @



  • Thanks a lot for the suggestions, I will look into it, I like the second option but the first option is also interesting, I didn't know about the options to break a loop. I will play around and see what I can come up with. Thanks lot.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.