4

i wanted to write a file search program where the user can enter the serach pattern(any valid regex) and the file name matching the same will be returned.

e.g MFile123.tx will find UMFile123.txt and AIIMFile123.txs

I tried the following, but it did not work:

import java.util.regex.*;
public class regexTest {
    public static void main(String... a){
        String file="UMFile123.txt";
       //String pattern="*MFile*.tx?"; TRIED with \*MFile*.tx , but no use
        String pattern="UMFile*.tx?";
        Pattern p=Pattern.compile(pattern);
        Matcher m=p.matcher(file);
        if(m.matches()){
            System.out.println("Hi!it matches!!");
        }
    }
}
Toon Krijthe
  • 52,876
  • 38
  • 145
  • 202
Anushree Acharjee
  • 854
  • 5
  • 15
  • 30
  • Manually escaping stuff is *not* a good idea as other answers here mention. Take a look at the usage of `quote` method used in my answer. – Sanjay T. Sharma Oct 11 '12 at 06:36

4 Answers4

2

The regular expression should be:

.*MFile123\.tx.*

.* matches any number characters before and after MFile123.tx

Also you need to escape the . before tx because

. refers to any character.

* refers zero or more occurrence of the particular character before it

So, .* means match 0 or more number of characters

Anirudha
  • 32,393
  • 7
  • 68
  • 89
  • Can't help but notice you kind of copied my regex there. I will take that as a compliment ,~) – Billy Moon Oct 11 '12 at 06:31
  • @BillyMoon hmm..it's just a coincidence..:) – Anirudha Oct 11 '12 at 06:33
  • thanks Anirudha!! it worked. But here the pattern is a user input. As * means zero or more characters and ? means zero or one, so if the pattern user enters *MFile123*.tx? both UMFile123.txt and AIIMFile123.txs should be matched. – Anushree Acharjee Oct 11 '12 at 06:34
  • 1
    @user1737079 `MFile123.tx?` in that case would match `MFile123.txx` OR `MFile123.tx` **not** `UMFile123.txt` and `AIIMFile123.txs ` – Anirudha Oct 11 '12 at 06:37
  • @BillyMoon I guess u wud have 2 write ur own regex engine if you dont want the natural regex matching – Anirudha Oct 11 '12 at 06:38
2

I would use regex as follows: .*MFile123\.tx.*

This breaks down as: zero or more of anything (.*) followed by MFile123 followed by literal . (escaped) followed by tx followed by zero or more of anything again (.*)

Billy Moon
  • 57,113
  • 24
  • 136
  • 237
1

The simplest solution would be to "quote" or "escape" the user entered file name/pattern and prepend & append a .*? to it. Something like:

final String userFname = "MFile123.tx";
final String escapedName = Pattern.quote(userFname);
final String fnamePattern = ".*?" + escapedName + ".*";
final Pattern pat = Pattern.compile(fnamePattern);
final Matcher m = pat.matcher(file);

I would rather not go with the business of manual escaping as mentioned by the other answers here. Tricky to get right IMHO. If you want case-insensitive match, just throw in one of the insensitive regex flags and you should be good.

Sanjay T. Sharma
  • 22,857
  • 4
  • 59
  • 71
  • thanks Sanjay!! but the problem is same. eg if filename->UMFile123.txt and pattern->U*.txt, then matching is not happening.SOPs are: excapedname:\QU*.txt\E filename->test.txt}{fnamePattern->.*?\QU*.txt\E.* please help. – Anushree Acharjee Oct 11 '12 at 13:58
  • I guess I misread your question. What you need is the "glob" pattern matching instead of regex matching. Have a look at [this question](http://stackoverflow.com/questions/1247772/is-there-an-equivalent-of-java-util-regex-for-glob-type-patterns) which provides a ready solution with alternatives. – Sanjay T. Sharma Oct 11 '12 at 15:05
0

You could use File.listFiles(FileFilter). Please have a look at the below example for better understanding:

package com.stackoverflow.works;

import java.io.File;
import java.io.FileFilter;
import java.text.SimpleDateFormat;
import java.util.regex.Pattern;

/*
 * @Author: sarath_sivan
 */

public class FileSearchService {

    /*
     * @Description: Method used to List the files
     * @param: directory File, regex String
     * @return: fileList File[]
     */
    public static File[] search(File directory, String regex) {
        if(!directory.isDirectory()) {
            throw new IllegalArgumentException(directory+" is no directory.");
        }

        final Pattern pattern = Pattern.compile(regex); // Caution: could also throw an exception!
        return directory.listFiles(new FileFilter(){
            @Override
            public boolean accept(File file) {
                return pattern.matcher(file.getName()).matches();
            }
        });
    }

    /*
     * @Description: Method used to print the File List
     * @param: fileList File[]
     * @return: void
     */
    public static void printFileList(File[] fileList) {
        for (File file : fileList) {
            System.out.println("File Name: " + file.getName());
            System.out.println("Absolute Path: " + file.getAbsolutePath());
            System.out.println("Last Modified: " + getLastModifiedTimestamp(file));
            System.out.println();
        }
    }

    /*
     * @Description: Method used to get the Last Modified Timestamp
     * @param: file File
     * @return: void
     */
    public static String getLastModifiedTimestamp(File file) {
        SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
        return sdf.format(file.lastModified());
    }

    /*
     * @Description: Main method used to test the Regex File listing logic
     * @param: fileList File[]
     * @return: void
     */
    public static void main(String[] args) {

        String directoryPath = "C:/Users/sarath_sivan/Desktop";
        File directory = new File(directoryPath);
        String regex = "([^\\s]+(\\.(?i)(jpg|png|gif|bmp))$)"; //Regular Expression pattern for image file extension

        File[] fileList = search(directory, regex);
        printFileList(fileList);

    }

}

This code lists the image files in a given directory with regex. A sample output look like this:

output

1218985
  • 7,531
  • 2
  • 25
  • 31