/* Objective: Since Windows 10 File Explorer search seems messed-up on my laptop (and computers of at least some others reporting online) since late 2019, try to make something for finding files/folders on my laptop while waiting for a fix! First just look at file/folder names (might include option to match text within files later) Now naming new intermediates/iterations/versions, after initial 10 just named FindFileOrFolder, with _vX suffixes, so this is... v1 (first version uploaded to website) 8Jan2020 --Dealt with the issue that prog displays temporary as well as regular files, I hope ...think excluding via Files.isHidden(...) works --Also changed the text in the depth button */ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Font; import java.awt.Insets; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.stream.Stream; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; class FindFileOrFolder_v1 { int walkDepth = 1; // --specifies how many subdirectory levels to go down when collecting files to access // initialized to default 1 (do not look in subdirectories) // GUI components... JFrame frame = new JFrame("FindFileOrFolder"); // which contains all the other GUI components... JPanel panelForInput = new JPanel(new BorderLayout()); JPanel panelForButtonsAndOutput = new JPanel(new BorderLayout()); JPanel panelForStartComponents = new JPanel(new BorderLayout()); JPanel panelForTargetComponents = new JPanel(new BorderLayout()); JLabel startFolderJLabel = new JLabel(" Enter the path of the folder from within which you want to (start your) search..."); JLabel targetNameJLabel = new JLabel(" Enter the name or partial name of a file or folder you want to find..."); JTextArea startFolderTextArea = new JTextArea(2, 60); // input to specify foolder within which to (start) searching JTextArea targetNameTextArea = new JTextArea(2, 60); // input to specify file/folder names for which to search JButton targetButton = new JButton("Find files/folders"); JButton depthButton = new JButton("Search in subfolders of the starting folder also"); JTextArea dTextArea = new JTextArea(40, 100); // displays output, i.e. paths for files/folders found FindFileOrFolder_v1() // constructor, called when main method runs { panelForStartComponents.add(startFolderJLabel, BorderLayout.NORTH); startFolderTextArea.setLineWrap(true); startFolderTextArea.setMargin(new Insets(5, 5, 5, 5)); panelForStartComponents.add(new JScrollPane(startFolderTextArea), BorderLayout.SOUTH); panelForInput.add(panelForStartComponents, BorderLayout.NORTH); panelForTargetComponents.add(targetNameJLabel, BorderLayout.NORTH); targetNameTextArea.setLineWrap(true); targetNameTextArea.setMargin(new Insets(5, 5, 5, 5)); panelForTargetComponents.add(new JScrollPane(targetNameTextArea), BorderLayout.SOUTH); panelForInput.add(panelForTargetComponents, BorderLayout.SOUTH); targetButton.addActionListener(actionEvent -> { dTextArea.setForeground(Color.BLACK); // (for searches following a no-valid-start-path message (red)) dTextArea.setText(null); // (first clear results of any previous search) String startText = startFolderTextArea.getText().trim(); Path startPath = Paths.get(startText); // path to folder within which to (start) searching boolean startPathValid = Files.isDirectory(startPath); // (unfortunately(?), empty string arg seems to // generate path regarded as valid (root/current folder?), so fo now adding check re startText.isEmpty() below) if (startText.isEmpty() || !startPathValid) { noValidStartMessage(); } final String target = targetNameTextArea.getText(); // (partial) names of files/folders for which to search if (!startText.isEmpty() && startPathValid && !target.isEmpty()) { // only run process below if target text and valid start path have been supplied try { Stream targetStream = Files.find(startPath, walkDepth, (p,a) -> !isHiddenHandler(p) && // --i11 added to exclude hidden files (temporary etc) p.getFileName().toString().contains(target)); targetStream.forEach(p -> dTextArea.append(p.toString() + "\n")); // print paths found in output/display area } catch (IOException ex) { if (ex.getClass().getName().equals("java.nio.file.NoSuchFileException")) { noValidStartMessage(); } // --probably not needed now, though, as should not get to try clause without valid start path } } } ); targetButton.setMargin(new Insets(10, 10, 10, 10)); targetButton.setFont(new Font("SansSerif", Font.BOLD, 20)); panelForButtonsAndOutput.add(targetButton, BorderLayout.NORTH); depthButton.addActionListener(actionEvent -> { if (walkDepth == 1) { walkDepth = Integer.MAX_VALUE; // depthButton.setText("Do not include subdirectories"); depthButton.setText("Search in the starting folder only"); } else // (walkDepth is Integer.MAX_VALUE) { walkDepth = 1; // depthButton.setText("Include subdirectories"); depthButton.setText("Search in subfolders of the starting folder also"); } } ); // toggles walk dept between no-subfolders and all-subfolders) panelForInput.add(depthButton, BorderLayout.CENTER); dTextArea.setEditable(false); dTextArea.setLineWrap(true); dTextArea.setMargin(new Insets(5, 5, 5, 5)); panelForButtonsAndOutput.add(new JScrollPane(dTextArea), BorderLayout.SOUTH); frame.add(panelForInput, BorderLayout.NORTH); frame.add(panelForButtonsAndOutput, BorderLayout.SOUTH); frame.setResizable(false); // (buttons disappear if user drags frame bottom up, // while if it's dragged down, the extra space just appears as a gap between the panels; // so best thing fot the moment is just to hard-code big dTextArea; // looking briefly online, see descriptions/code for how to make rezizable by dragging, but not trivial frame.setVisible(true); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); // (may need to keep this positioned last) } void noValidStartMessage() // puts message in display area if no valid start path is supplied { dTextArea.setForeground(Color.red); dTextArea.setText("No valid start path supplied"); } // --i11 added as Files.isHidden(...) throws checked exception so awkward when called directly in stream above boolean isHiddenHandler (Path p) { boolean result = false; try { result = Files.isHidden(p); } catch (IOException ex) { System.out.println(ex); } return result; } public static void main(String[] args) { new FindFileOrFolder_v1(); } }