Nested find in files to get a list of files with two words anywhere in file

Nested find in files to get a list of files with two words anywhere in file

74
Advanced UserAdvanced User
74

    May 28, 2020#1

    Is it possible to make a script that takes two keywords in and does a find in files on the first key, then with the results of that find in file search, search those results for the second keyword?

    Thank you for looking into this.
    Max

    6,686585
    Grand MasterGrand Master
    6,686585

      May 29, 2020#2

      Yes, that is possible.

      Are the two keywords on same line or on different lines in the file?

      Are the two keywords always in same order?

      If the keywords are on different lines, but always in same order, how much data is usually between the two keywords?
      Best regards from an UC/UE/UES for Windows user from Austria

      74
      Advanced UserAdvanced User
      74

        Jun 01, 2020#3

        Sorry for my delayed response. The two keywords are on different lines. The user would be prompted for each keyword so their order matters with what the first and second prompt may be. Also the keywords could be two words, "R4i viewer", "CSDB".

        6,686585
        Grand MasterGrand Master
        6,686585

          Jun 01, 2020#4

          When I have understood you correct, a single Perl regular expression Find in Files with search expression (?s)R4i viewer.+?\KCSDB would be enough to find the files containing first the string R4i viewer and second anywhere below the string CSDB with listing just the line containing CSDB if there are not too many characters between the two strings.
          Best regards from an UC/UE/UES for Windows user from Austria

          74
          Advanced UserAdvanced User
          74

            Jun 02, 2020#5

            Yes but we can make it even easier. Do the find in files to search for one instance of "R4i Viewer". Then on the files found do another find in files that will search for one occurrence of "CSDB". We don't need a count or line number the key phrase fell on. We just need confirmation the files has an occurrence of the key phrase.

            6,686585
            Grand MasterGrand Master
            6,686585

              Jun 03, 2020#6

              Running first a Find in Files on all files in a folder (tree) for first string to find and next one more Find in Files on the files containing the first searched string is slower and more difficult to code. It would be easier and faster to do this with a simple batch file or with PowerShell than with using an UltraEdit script. Other programs like UltraFinder or Total Commander are also better applications to get just a list of files containing two strings than text editor UltraEdit.

              However, I coded an UltraEdit script which I think is as fast as possible. The folder path at top must be defined correct. The two search strings can be also defined at top. The user executing the script is prompted for each search string being defined at top as empty string. The Find in Files parameters at top of the function define how Find in Files is run on specified folder (tree). The result is always written to output window automatically opened by the script.

              Code: Select all

              var g_sFolder = "C:\\Temp\\"
              var g_sSearch1 = "";
              var g_sSearch2 = "";
              
              UltraEdit.selectClipboard(9);
              getFileNamesList();
              UltraEdit.clearClipboard();
              UltraEdit.selectClipboard(0);
              UltraEdit.outputWindow.showWindow(true);
              UltraEdit.outputWindow.showStatus=false;
              
              function getFileNamesList ()
              {
                 UltraEdit.outputWindow.clear();
              
                 UltraEdit.ueReOn();
                 UltraEdit.frInFiles.regExp=false;
                 UltraEdit.frInFiles.matchWord=false;
                 UltraEdit.frInFiles.matchCase=false;
                 UltraEdit.frInFiles.filesToSearch=0;
                 UltraEdit.frInFiles.searchSubs=false;
                 UltraEdit.frInFiles.searchInFilesTypes="*";
                 UltraEdit.frInFiles.directoryStart=g_sFolder;
                 UltraEdit.frInFiles.ignoreHiddenSubs=true;
                 UltraEdit.frInFiles.useOutputWindow=true;
                 UltraEdit.frInFiles.reverseSearch=false;
                 UltraEdit.frInFiles.unicodeSearch=false;
                 UltraEdit.frInFiles.useEncoding=false;
              
                 // Get first just a list of file names matching the file type pattern
                 // (* is for all files) in the specified directory (with not searching
                 // in subdirectories at all) written into the output window. This is a
                 // pure file system access. There is no file searched for a string.
                 UltraEdit.frInFiles.find("");
                 UltraEdit.outputWindow.copy();
                 UltraEdit.outputWindow.clear();
                 var asFileNames1 = UltraEdit.clipboardContent.split("\r\n");
              
                 // Remove the last two lines not containing a file name as being usually
                 // the summary information and an empty line which are not needed at all.
                 while (asFileNames1.length)
                 {
                    if (asFileNames1[asFileNames1.length-1].indexOf('\\') >= 0) break;
                    asFileNames1.pop();
                 }
                 if (!asFileNames1.length)
                 {
                    UltraEdit.outputWindow.write("There are no "+ UltraEdit.frInFiles.searchInFilesTypes +
                              " files found in folder" + (UltraEdit.frInFiles.searchSubs ? " tree of" : "") +
                              ": " + g_sFolder);
                    return;
                 }
              
                 // Prompt the script user for the first search string
                 // if an empty string is defined at top of this script.
                 while (!g_sSearch1.length)
                 {
                    g_sSearch1 = UltraEdit.getString("Please enter first string to find:",1);
                 }
              
                 // Get a list of files NOT containing the first string to find.
                 // Each caret character must be escaped in a literal search string
                 // because it is by default the escape character in a non-regex string.
                 UltraEdit.frInFiles.reverseSearch=true;
                 UltraEdit.frInFiles.find(g_sSearch1.replace(/\^/g,"^^"));
                 UltraEdit.outputWindow.copy();
                 UltraEdit.outputWindow.clear();
                 var asFileNames2 = UltraEdit.clipboardContent.split("\r\n");
              
                 // Remove all lines from output not containing a file name.
                 while (asFileNames2.length)
                 {
                    if (asFileNames2[0].indexOf('\\') >= 0) break;
                    asFileNames2.splice(0,1);
                 }
                 while (asFileNames2.length)
                 {
                    if (asFileNames2[asFileNames2.length-1].indexOf('\\') >= 0) break;
                    asFileNames2.pop();
                 }
              
                 // Is the number of files not containing the searched string
                 // identical to the number of files searched for this string?
                 if (asFileNames1.length == asFileNames2.length)
                 {
                    UltraEdit.outputWindow.write('There is no file containing the string "' +
                                                 g_sSearch1 + '" in folder: ' + g_sFolder);
                    return;
                 }
              
                 // Remove from first file names list all file names from second list
                 // to get the file names of the files containing the searched string.
                 for (var nIndex2 = 0; nIndex2 < asFileNames2.length; nIndex2++)
                 {
                    for (var nIndex1 = 0; nIndex1 < asFileNames1.length; nIndex1++)
                    {
                       if (asFileNames1[nIndex1] == asFileNames2[nIndex2])
                       {
                          asFileNames1.splice(nIndex1,1);
                          break;
                       }
                    }
                 }
              
                 // Prompt the script user for the first search string
                 // if an empty string is defined at top of this script.
                 if (!g_sSearch2.length)
                 {
                    var sPrompt = "Found the first string in " + asFileNames1.length + " file" +
                        ((asFileNames1 == 1) ? "" : "s") + ".\n\nPlease enter second string to find:";
                    do
                    {
                       g_sSearch2 = UltraEdit.getString(sPrompt,1);
                    }
                    while (!g_sSearch2.length)
                 }
              
                 // Search in each file containing the first string for the
                 // second string again with a reverse search and create a
                 // list of file names containing the second searched string.
                 asFileNames2 = [];
                 UltraEdit.frInFiles.directoryStart=""
                 var sSearch2 = g_sSearch2.replace(/\^/g,"^^");
                 for (nIndex1 = 0; nIndex1 < asFileNames1.length; nIndex1++)
                 {
                    UltraEdit.frInFiles.searchInFilesTypes = asFileNames1[nIndex1];
                    UltraEdit.frInFiles.find(sSearch2);
                    UltraEdit.outputWindow.copy();
                    UltraEdit.outputWindow.clear();
                    if (UltraEdit.clipboardContent.indexOf(asFileNames1[nIndex1]) < 0)
                    {
                       asFileNames2.push(asFileNames1[nIndex1]);
                    }
                 }
              
                 // Was the second string not found in any file from the list?
                 if (!asFileNames2.length)
                 {
                    UltraEdit.outputWindow.write('There is no file containing also the string "' +
                                                 g_sSearch2 + '" in folder: ' + g_sFolder);
                    return;
                 }
              
                 // Output the list of file names containing both strings.
                 UltraEdit.outputWindow.write("File" + ((asFileNames2.length==1) ? "" : "s") +
                           ' containing "' + g_sSearch1 + '" and "' + g_sSearch2 + '":\n');
              
                 UltraEdit.outputWindow.write(asFileNames2.join("\n"));
              }
              
              PS: It is possible to specify a semicolon separated list of file names for UltraEdit.frInFiles.searchInFilesTypes. I have never tried how long the list of file names can be and it is unclear if this script is used on 5 files or 50.000 files and how long are the full qualified file names. For that reasons the script is written to run the second (reverse) find on each file of the list of files with first searched string separately one after the other which is not optimal, but still fast.
              Best regards from an UC/UE/UES for Windows user from Austria

              74
              Advanced UserAdvanced User
              74

                Jun 03, 2020#7

                Thanks Mofi I'll take a look and play with it. I appreciate your help.