tags:

views:

111

answers:

3

My basic intention is to find out whether a dir say A is immediately inside dir B or not. I'm checking it in java so I'm using Pattern and Matcher classes.

let say homeDir = /aa/bb/cc (home dir) dirB = /aa/bb/cc/dd/ee (not immediately inside home dir) dirC = /aa/bb/cc/dd (immediately inside home dir) dirD = /aa/ff (outside home dir)

I want the output to be true if the dir is immediately inside homeDir, otherwise false. My approach is I'm checking if homeDir path is matching with the given dir path. If it matches, I'm checking whether there are any / after the homeDir part. This is my sample code

private static final String REGEX =
                             "homeDir"+"/"+"((.+)(/?)(.+))";
private static final String INPUT =
                            "/aa/bb/cc/dd/ee";

public static void main(String[] args) {
   Pattern p = Pattern.compile(REGEX);
   Matcher m = p.matcher(INPUT); // get a matcher object
   boolean output = false;
   while(m.find()) {
      System.out.println("Total : "+m.group(1)+"First : "+m.group(2)+ "Slash : "+m.group(3)+"Last : "+m.group(4));
            if(m.group(3).length()==0)
            {// that means match found and immediately inside also
              output = true;

            }
   }

The out put I get is Total : dd/eeFirst : dd/eSlash : Last : e. All I wanted is I want the slash to be captured if there exists any. I think first .+ is greedy and taking all. I tried with possessive quantifier (/?+) but it throwing Exception in thread "main" java.util.regex.PatternSyntaxException: At position 3 in regular expression pattern: attempted to repeat a token that is already repeated /aa/bb/cc/((.+)(/?+)(.+)) ^ Please help me hot to go about this problem

A: 
Pattern p = Pattern.compile("/aa/bb/cc/([^/]+)");
Matcher m = p.matcher(input);
boolean output = m.matches();
if (output)
  System.out.println(m.group(1));
erickson
+6  A: 

First, you should use File and not RegEx as it can resolve all alias file like '~' or '.' or '..'.


String  aFileName   = "...";
File    aAbsFile    = (new File(aFileName)).getAbsolutePath(); // Resolve Alias here
File    aAbsHome    = (new File(aHomeDir)) .getAbsolutePath(); // Resolve Alias here
boolean aIsImmediet = aFile.getParent().getCanonicalPath().equals(aAbsHome.getCanonicalPath());

Second, if you are sure there is not alias, another way you can do is subtract and contain.


String  aFileName    = "...";
boolean aIsImmedient = aFileName.substring(aHomeDir.length).contain('/');

The reason why I suggest these two because they are faster than RegEx.

If you still want RegEx, Use '"homeDir/([^/]+)/([^/]+)"' and you printing will be:


System.out.print("Total : %s; First: %s; Last: %s"
    m.group(0), // All match
    m.group(1), // First  '(..)'
    m.group(2)  // Second '(..)'
);

You use '/' alone with out '(...)' and '?', use '[^/]' (not a /) because you want it to be there to proof the match of only one '/' and no more.

Hope this helps.

NawaMan
Mostly correct. However, 1) you must use `getCanonicalPath()`, 2) it will not resolve `"~"`, 3) it WILL resolve symbolic links and/or drive names (depending on OS platform), and 4) `"."` and `".."` are not strictly speaking aliases.
Stephen C
Hey Stephen Cobert, You are right, about `getCanonicalPath()`, I will fix that. :D
NawaMan
+1  A: 

if you only want to know if a file/folder is IMMEDIATELY inside another, you don't need REGEXP.

public static boolean isImmediateParent(String parentPath, String childPath)
{
 int index = childPath.lastIndexOf("/");
 if (index == -1)
  throw new IllegalArgumentException("child has no parent");
 return childPath.substring(0, index).equals(parentPath);
}

isImmediateParent("a", "a") = exception
isImmediateParent("a", "a/b") = true
isImmediateParent("a", "a/b/c") = false
isImmediateParent("a", "b/a") = false
pstanton
simple and effective
ram
yeah, although keep in mind different file separators on different os - to handle that i'd do a .replaceAll("\\\\","/") on both parameters at the start which is simpler than using the appropriate separator.
pstanton