• Login
Community
  • Login

Save found files?

Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
26 Posts 5 Posters 3.0k Views
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P
    Patricia Mayer
    last edited by Nov 19, 2019, 4:05 PM

    Hi all,

    I haven’t found a thread about this, so here is my question:

    Is there any possibility to save all files found in a find-in-files-search without having to open each one?

    Thanks & Regards
    Patricia

    E 1 Reply Last reply Nov 19, 2019, 4:10 PM Reply Quote 0
    • E
      Ekopalypse @Patricia Mayer
      last edited by Nov 19, 2019, 4:10 PM

      @Patricia-Mayer

      Not quite sure I understand what you try to achieve.
      Are you interested in the filenames containing the searched text?
      Are those files already open and, possibly, in a modified state and you want to save all of them?
      Something else?

      1 Reply Last reply Reply Quote 0
      • P
        Patricia Mayer
        last edited by dinkumoil Nov 19, 2019, 4:58 PM Nov 19, 2019, 4:23 PM

        I uploaded a screenshot for a better understanding:

        Search results

        The search term was found in 228 files that are stored in several different subfolders. I would like to save all 228 files in a different location/folder.

        E 1 Reply Last reply Nov 19, 2019, 5:44 PM Reply Quote 0
        • E
          Ekopalypse @Patricia Mayer
          last edited by Nov 19, 2019, 5:44 PM

          @Patricia-Mayer

          No, there is no such feature builtin in but if this is something you need more often you could create a batch file and follow a procedure.
          Something like:

          • do your search
          • drag and drop the result in a file which a fixed name (it needs to be drag and drop)
          • replace the unneeded content by using a regex like
            find what: (?-is)(?:(?:^Search "|\tLine).*\R| \(\d+ hits?\))
            replace with is empty
            press replace all (or record once a macro and run macro after drag and drop
          • run via Run menu something like:
            cmd /k FOR /F %i IN (D:\FIXED_NAME_FILE) DO copy %i D:\temp\put_it_in_here\

          If you replace cmd /k by cmd /c shell window gets closed automatically.

          A 1 Reply Last reply Nov 19, 2019, 6:32 PM Reply Quote 3
          • A
            Alan Kilborn @Ekopalypse
            last edited by Nov 19, 2019, 6:32 PM

            @Ekopalypse said in Save found files?:

            drag and drop the result in a file with a fixed name

            Meaning select the desired result data in the Find result window, and then drag-n-drop that.

            it needs to be drag and drop

            Why does it need to be drag-n-drop? Wouldn’t ctrl+c be the same?

            E 1 Reply Last reply Nov 19, 2019, 6:38 PM Reply Quote 2
            • E
              Ekopalypse @Alan Kilborn
              last edited by Nov 19, 2019, 6:38 PM

              @Alan-Kilborn

              Meaning select the desired result data in the Find result window, and then drag-n-drop that.

              Yes, ctrl+c does not copy the filenames, only the content found, at least for me, do you see different behavior on your side?

              A 1 Reply Last reply Nov 19, 2019, 7:38 PM Reply Quote 0
              • A
                Alan Kilborn @Ekopalypse
                last edited by Nov 19, 2019, 7:38 PM

                @Ekopalypse said in Save found files?:

                ctrl+c does not copy the filenames, only the content found, at least for me, do you see different behavior on your side?

                I do see different behavior; to me your result seems like a right-click copy operation in the Find-result window.

                Here’s some results for me (I did a ctrl+a in the Find-result window, then 3 different copy/paste ops into a new editor tab):

                c82ef8ee-8629-476a-b42d-41c214503ace-image.png

                E 1 Reply Last reply Nov 19, 2019, 7:48 PM Reply Quote 1
                • E
                  Ekopalypse @Alan Kilborn
                  last edited by Nov 19, 2019, 7:48 PM

                  @Alan-Kilborn

                  that is strange, I only see the searched content, regardless if I select all
                  or only partial results. The first line and every “filename line” gets stripped off.
                  I’m testing this on 7.8.1

                  A 1 Reply Last reply Nov 19, 2019, 8:05 PM Reply Quote 0
                  • A
                    Alan Kilborn @Ekopalypse
                    last edited by Nov 19, 2019, 8:05 PM

                    @Ekopalypse said in Save found files?:

                    I’m testing this on 7.8.1

                    I still use 7.8 day-to-day so my previous results were with that. But…switching to 7.8.1 (64 bits) temporarily I do not see any change; meaning that I don’t see it working the way you do!

                    1 Reply Last reply Reply Quote 0
                    • A
                      Alan Kilborn
                      last edited by Alan Kilborn Nov 19, 2019, 8:15 PM Nov 19, 2019, 8:14 PM

                      So before this thread was started earlier today, I had some Pythonscript code for manipulating text in the Find-result window (that I never really finished or did anything with):

                      import ctypes
                      from ctypes.wintypes import BOOL, HWND, LPARAM
                      import re
                      
                      class FindResultPanel(object):
                      
                          def __init__(self):
                      
                              WNDENUMPROC = ctypes.WINFUNCTYPE(BOOL, HWND,LPARAM)
                              FindWindow = ctypes.windll.user32.FindWindowW
                              GetWindowText = ctypes.windll.user32.GetWindowTextW
                              GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW
                              SendMessage = ctypes.windll.user32.SendMessageW
                              EnumChildWindows = ctypes.windll.user32.EnumChildWindows
                              GetClassName = ctypes.windll.user32.GetClassNameW
                              curr_class = ctypes.create_unicode_buffer(256)
                      
                              tag1 = 0
                      
                              find_result_panel_scintilla_handle_list = []
                      
                              def foreach_window(hwnd, lParam):
                                  tag2 = 1
                                  if lParam == tag1:
                                      cc = curr_class[:GetClassName(hwnd, curr_class, 256)]
                                      if cc == u'#32770':
                                          length = GetWindowTextLength(hwnd)
                                          if length > 0:
                                              buff = ctypes.create_unicode_buffer(length + 1)
                                              GetWindowText(hwnd, buff, length + 1)
                                              if buff.value == u'Find result':
                                                  EnumChildWindows(hwnd, WNDENUMPROC(foreach_window), tag2)
                                  elif lParam == tag2:
                                      cc = curr_class[:GetClassName(hwnd, curr_class, 256)]
                                      length = GetWindowTextLength(hwnd)
                                      if length > 0:
                                          buff = ctypes.create_unicode_buffer(length + 1)
                                          GetWindowText(hwnd, buff, length + 1)
                                          if cc == u'Scintilla':
                                              find_result_panel_scintilla_handle_list.append(hwnd)
                                              return False  # stop enumeration
                                  return True  # continue enumeration
                      
                              EnumChildWindows(FindWindow(u'Notepad++', None), WNDENUMPROC(foreach_window), tag1)
                      
                              try:
                                  hwnd = find_result_panel_scintilla_handle_list[-1]
                              except IndexError:
                                  raise RuntimeError('No Find result window found')
                      
                              self.hwnd = hwnd
                      
                              # from Scintilla.iface ( https://github.com/notepad-plus-plus/notepad-plus-plus/blob/master/scintilla/include/Scintilla.iface )
                              # Retrieve a pointer value to use as the first argument when calling the function returned by GetDirectFunction.
                              #get int GetDirectPointer=2185(,)
                              self.direct_pointer = SendMessage(self.hwnd, 2185, 0, 0)
                      
                          def GetText(self):
                      
                              # https://www.scintilla.org/ScintillaDoc.html#SCI_GETTEXT
                              # Retrieve all the text in the document.
                              # Returns number of characters retrieved.
                              # Result is NUL-terminated.
                              #fun position GetText=2182(position length, stringresult text)
                              # position -> intptr_t position in a document
                              # stringresult -> pointer to character, NULL-> return size of result
                              length_of_text = ctypes.WinDLL('SciLexer.dll', use_last_error=True).Scintilla_DirectFunction(self.direct_pointer, 2182, 0, 0)
                              text_of_document = ctypes.c_char_p('\0' * (length_of_text + 1))  # allocate buffer to hold text
                              ctypes.WinDLL('SciLexer.dll', use_last_error=True).Scintilla_DirectFunction(self.direct_pointer, 2182, length_of_text, text_of_document)
                              return text_of_document.value
                      
                          def GetFoldLevel(self, line_number):
                      
                              # https://www.scintilla.org/ScintillaDoc.html#SCI_GETFOLDLEVEL
                              # Retrieve the fold level of a line.
                              #get FoldLevel GetFoldLevel=2223(line line,)
                              SC_FOLDLEVELNUMBERMASK = 0x0FFF
                              return ctypes.WinDLL('SciLexer.dll', use_last_error=True).Scintilla_DirectFunction(self.direct_pointer, 2223, line_number, 0) & SC_FOLDLEVELNUMBERMASK
                      
                          def GetFoldExpanded(self, line_number):
                      
                              # https://www.scintilla.org/ScintillaDoc.html#SCI_GETFOLDEXPANDED
                              # Is a header line expanded?
                              #get bool GetFoldExpanded=2230(line line,)
                              return ctypes.WinDLL('SciLexer.dll', use_last_error=True).Scintilla_DirectFunction(self.direct_pointer, 2230, line_number, 0)
                      
                      try:
                      
                          find_result_panel = FindResultPanel()
                      
                      except RuntimeError:
                      
                          notepad.messageBox('Could not find Find-result window;\r\nMaybe you have not yet run a search that would create it?', '')
                      
                      else:
                      
                          find_result_text = find_result_panel.GetText()
                      
                          print_all = True if 0 else False
                          copy_line_info_that_user_can_see = True if 0 else False
                          copy_filepaths_that_user_can_see = True if 1 else False
                          unique_filepaths_list = []
                      
                          recent_start_expanded = True
                          recent_filepath_expanded = True
                          for (line_number, line_contents) in enumerate(find_result_text.splitlines()):
                              if print_all:
                                  print(line_number, find_result_panel.GetFoldLevel(line_number), find_result_panel.GetFoldExpanded(line_number), line_contents)
                              else:
                                  if line_contents.startswith('Search'):
                                      recent_start_expanded = True if find_result_panel.GetFoldExpanded(line_number) else False
                                  elif line_contents.startswith(' '):
                                      recent_filepath_expanded = True if find_result_panel.GetFoldExpanded(line_number) else False
                                  if copy_line_info_that_user_can_see:
                                      if line_contents.startswith('Search'):
                                          if waiting_for_start:
                                              pass
                                  elif copy_filepaths_that_user_can_see:
                                      if line_contents.startswith(' '):
                                          if recent_start_expanded:
                                              _ = re.sub(r'^\s+(.+?) \(\d+\shits?\)$', r'\1', line_contents)
                                              if _ not in unique_filepaths_list: unique_filepaths_list.append(_)
                      
                          if copy_filepaths_that_user_can_see:
                              for _ in unique_filepaths_list: print(_)
                      

                      In this script, we see in the last line that there is something called unique_filepaths_list.

                      We can put this to use for the OP’s task by adding a bit more code at the bottom:

                          keep_going = True
                          while keep_going:
                              destination_dir = notepad.prompt('Enter destination directory:', 'Copy files with hits', '')
                              if destination_dir == None:
                                  keep_going = False  # cancel was pressed
                              elif os.path.isdir(destination_dir): break
                      
                          if keep_going:
                              from shutil import copy
                              for source_file in unique_filepaths_list:
                                  try:
                                      copy(source_file, destination_dir)
                                  except:
                                      notepad.messageBox('Problem copying the file:\r\n"{}"\r\nto the folder:\r\n"{}"'.format(source_file, destination_dir), '')
                      

                      Running the code now (after doing a search that populates the Find-result window with the desired results) will result in the following popup prompt:

                      902c3a28-8c7e-490c-9b8a-c09c9bd58b53-image.png

                      Putting a valid folder name in the box and pressing OK will complete the desired copy operation.

                      1 Reply Last reply Reply Quote 4
                      • A
                        Alan Kilborn
                        last edited by Alan Kilborn Nov 19, 2019, 8:25 PM Nov 19, 2019, 8:24 PM

                        I probably also should add that the files copied by the script are going to be the disk copies of the files. Notepad++ does an in-memory search rather than a disk search when it produces its hit list. So if any of the hit files are dirty/modified/red-iconned when the search is conducted, the file contents that actually get copied are going to be different than the modified contents.

                        TL;DR: Save all Notepad++ files (so that none have red icons) before running the script – or when doing Eko’s originally suggested solution!

                        1 Reply Last reply Reply Quote 2
                        • guy038G
                          guy038
                          last edited by guy038 Nov 19, 2019, 9:29 PM Nov 19, 2019, 9:28 PM

                          Hi, @ekopalypse, @alan-kilborn and All,

                          I did a quick test and I confirm that the Alan’s behavior seems to be the default one !

                          My configuration :

                          Notepad++ v7.8.1   (32-bit)
                          Build time : Oct 27 2019 - 22:46:07
                          Path : D:\@@\781\notepad++.exe
                          Admin mode : OFF
                          Local Conf mode : ON
                          OS Name : Microsoft Windows XP (32-bit) 
                          OS Build : 2600.0
                          Plugins : DSpellCheck.dll ExtSettings.dll mimeTools.dll NppConverter.dll NppExport.dll 
                          

                          • A Ctrl + A action ( or right-click on the Select All option ), followed with an Ctrl + C action and, finally, a Ctrl + V action, in a new tab, do copy all Find result contents. So your regex works fine, extracting the absolute pathnames of all the files involved in the search !

                          • A Ctrl + A action ( or right-click on the Select All option ), followed with a right-click on the Copy option and, finally, a Ctrl + V action, in a new tab, only copy the lines, containing the matched string, from all the files scanned, in the Find result window

                          May be a plugin issue ?

                          Best Regards

                          guy038

                          A PeterJonesP 2 Replies Last reply Nov 20, 2019, 1:20 PM Reply Quote 2
                          • A
                            Alan Kilborn @guy038
                            last edited by Nov 20, 2019, 1:20 PM

                            @guy038 said :

                            May be a plugin issue ?

                            This is a good point. @Ekopalypse can you try testing this copy/paste behavior again with a very-clean 7.8.1?

                            1 Reply Last reply Reply Quote 0
                            • PeterJonesP
                              PeterJones @guy038
                              last edited by Nov 20, 2019, 2:03 PM

                              @guy038 said in Save found files?:

                              • A Ctrl + A action ( or right-click on the Select All option ), followed with an Ctrl + C action and, finally, a Ctrl + V action, in a new tab, do copy all Find result contents. So your regex works fine, extracting the absolute pathnames of all the files involved in the search !

                              • A Ctrl + A action ( or right-click on the Select All option ), followed with a right-click on the Copy option and, finally, a Ctrl + V action, in a new tab, only copy the lines, containing the matched string, from all the files scanned, in the Find result window

                              I thought I would emphasize this to @Ekopalypse : the behavior is different depending on whether you use keystrokes or menu selection for the copy. I just replicated this on portable 7.8.1-64bit. If you use the Ctrl+C keystroke, it copies the filename; if you use RClick > Copy, it only copies the lines, not the filenames. (I also confirmed that you cannot use File > Copy, because that’s using the active editor window, even when Find result is the foreground pane.) I pasted not only into Notepad++, but into other apps as well, confirming that it’s actually the copy-operation that’s different depending on Ctrl+C vs RClick > Copy.

                              I went back to my 7.7.1-64bit, and it behaves the same way, with Ctrl+C vs RClick > Copy having separate behavior.

                              A 1 Reply Last reply Nov 20, 2019, 2:16 PM Reply Quote 2
                              • A
                                Alan Kilborn @PeterJones
                                last edited by Nov 20, 2019, 2:16 PM

                                @PeterJones said:

                                (I also confirmed that you cannot use File > Copy, because that’s using the active editor window, even when Find result is the foreground pane.)

                                Presume you meant:

                                (I also confirmed that you cannot use Edit > Copy, because that’s using the active editor window, even when Find result is the foreground pane.)

                                1 Reply Last reply Reply Quote 2
                                • E
                                  Ekopalypse
                                  last edited by Nov 20, 2019, 6:40 PM

                                  I’m still a little bit confused as it seems to work most of the time like Peter described
                                  but sometimes it doesn’t, means I don’t get the filename lines copied into clipboard.
                                  Using a fresh portable 7.8.1 x64 version. Need to do further tests to see if I can find
                                  a reproducible way.

                                  1 Reply Last reply Reply Quote 1
                                  • P
                                    Patricia Mayer
                                    last edited by Patricia Mayer Nov 21, 2019, 4:48 PM Nov 21, 2019, 4:46 PM

                                    @Alan-Kilborn FANTASTIC! Thank you so much, it works perfectly. My colleague and I are delighted. :))

                                    Thank you other guys as well.

                                    Awesome forum.

                                    1 Reply Last reply Reply Quote 2
                                    • A
                                      Alan Kilborn
                                      last edited by Dec 2, 2019, 7:59 PM

                                      My script code has a .getText function on the FindResultPanel object.
                                      With it I can, obviously, get the text of the Find-result window.
                                      However, I’d like to be able to get the matching text, but I don’t know how to accomplish this.
                                      Visually, I can see the hit results in the window as red text on a yellow background.
                                      Anyone know how I can pull this information?

                                      E 1 Reply Last reply Dec 3, 2019, 10:39 PM Reply Quote 0
                                      • E
                                        Ekopalypse @Alan Kilborn
                                        last edited by Dec 3, 2019, 10:39 PM

                                        @Alan-Kilborn

                                        Why not using the styling information to identify the matched text?

                                        A 2 Replies Last reply Dec 4, 2019, 1:42 PM Reply Quote 2
                                        • A
                                          Alan Kilborn @Ekopalypse
                                          last edited by Dec 4, 2019, 1:42 PM

                                          @Ekopalypse said in Save found files?:

                                          Why not using the styling information to identify the matched text?

                                          Well, TBH when I earlier went searching in the N++ source code for SCE_SEARCHRESULT_*, I saw no occurrences of SCE_SEARCHRESULT_WORD2SEARCH occurring at all, so I was confused as to how it worked and was thinking it might not be possible at all to get this info via PS, even with ctypes usage.

                                          But with some experimentation with SCI_GETSTYLEAT it seems that I can recall the info; for example, in my “hit” text I get a style result of 4, which is indeed SCE_SEARCHRESULT_WORD2SEARCH.

                                          Is N++ source using hardcoded magic numbers for this instead of the “tags”, or some other mechanism that is strange or at least isn’t clear to me?

                                          Hmm, had a thought to search the Scintilla part of N++, where I do see SCE_SEARCHRESULT_WORD2SEARCH used. That must be how it is done.

                                          1 Reply Last reply Reply Quote 2
                                          • First post
                                            Last post
                                          The Community of users of the Notepad++ text editor.
                                          Powered by NodeBB | Contributors