• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 294
  • Last Modified:

Search for a specific directory and return the name in Java

Hi All,

I'm having trouble asking this question, so I am trying to ask it again, only simpler.  Originally asked this question on this post:http://www.experts-exchange.com/Programming/Languages/Java/Q_26920584.html.

First, let me say that java isn't my strong suite.  In fact, I have just pieced together enough to get myself in trouble.

Basically I have inherited some java code that searches for a specific directory in Linux in Slackware 12.  I want to move the program to Slackware 13, but it has a slightly different directory structure.  I have tried to tweak the code myself, but I'm not having much success.  Please see the attached old code -vs- the code I have edited.  I would like help in determining why it's returning null when the directory is actually there and it's not a hidden directory.

Here is the directory structure on Slackware 12:

/sys/bus/usb/devices/1-3/1-3:1.0/hostXX/targetXX:0:0/XX:0:0:0/block:sd_@ - the XX is some number and the '_" is a letter representing the block device id (sda, sdb, sdc, etc).

The information I want the program to retrieve is the "sd_".

Here is the directory structure on Slackware 13:

/sys/bus/usb/devices/1-3/1-3:1.0/hostXX/targetXX:0:0/XX:0:0:0/block/sd_


So you can see, it is slightly different.  The code for Test1.java just finds the start directory, then the Test2.java searches the specific sub directories until it finds one whose name starts with "block".  Then it returns the directory name back to Test1 who then picks off the last few characters to get the "sd_".

So in the edits I did, i changed the directories to search in Test2.java  and added "block" as one of the criteria, and I changed the filter to startsWith("sd").  So I think Test2.java should just return the "sd_" to Test1.java and I can just output that.  It seems to be searching the right directories, but it's returning null.

I would appreciate some help here.  I think this will be easy for someone familiar with Java. Test1.java Test2.java NewTest1.java NewTest2.java
0
Elena Quinn
Asked:
Elena Quinn
  • 12
  • 10
  • 6
2 Solutions
 
CEHJCommented:
What is your goal with this - to mount the device or what?
0
 
Elena QuinnAuthor Commented:
HI CEHJ,

The ultimate goal and what this program does is starts a thread which tests each device it finds that matches the criteria.  It claims the USB interface and then issues vendor specific command to the device to test the drive that's on the other side of the USB bridge.

Is that what you wanted to know?

Thanks.
0
 
Elena QuinnAuthor Commented:
Furthermore, the reason I need to move to Slackware 13, is because it has native support for USB 3.0.
0
Introducing Cloud Class® training courses

Tech changes fast. You can learn faster. That’s why we’re bringing professional training courses to Experts Exchange. With a subscription, you can access all the Cloud Class® courses to expand your education, prep for certifications, and get top-notch instructions.

 
CEHJCommented:
Well as i mentioned earlier, it would be easier to Runtime.exec find wouldn't it? Does the following find it?
find /sys/bus/usb/devices/1-3/1-3:1.0/hostXX -name sd_\*

Open in new window

0
 
for_yanCommented:


Or you may recursively traverse the folders in /sys/bus/usb/devices/1-3/1-3:1.0/hostXX
and then checking the file name for being sda, sdb, etc.

based on the exceprt from this:
http://helpdesk.objects.com.au/java/how-to-recursively-traverse-a-directory-tree

you can probably get the ArrayList with full paths to your devices using something like this method:


public static ArrayList traverse(File directory)
{
ArrayList al = new ArrayList();
   // Get all files in directory

   File[] files = directory.listFiles();
   for (File file : files)
   {
      if (file.isDirectory())
      {
         // Its a directory so (recursively) traverse it

         traverse(file);
      }
      else
      {
      if(file.getName().length() == 3 && file.getName().startsWith("sd")){
  al.add(f.getAbsolutePath());
 
 }
      }
   }
}
0
 
for_yanCommented:
correction of small mistake:

public static ArrayList traverse(File directory)
{
ArrayList al = new ArrayList();
   // Get all files in directory

   File[] files = directory.listFiles();
   for (File file : files)
   {
      if (file.isDirectory())
      {
         // Its a directory so (recursively) traverse it

         traverse(file);
      }
      else
      {
      if(file.getName().length() == 3 && file.getName().startsWith("sd")){
  al.add(file.getAbsolutePath());
 
 }
      }
   }
}

Open in new window

0
 
Elena QuinnAuthor Commented:
Well, you said:

Why not parse the output of

find /dev/disk/by-id

or

find /dev/disk/by-uuid

Open in new window


which didn't match the USB device# to the block device id.  But, I tried the find that you just posted, and it does work when the directory structure is hard coded, but the directories and sub directories are not always going to be the same.  It could be 1-4, or 1-6 and it could be 'host' or 'target' followed by any number.  So when i tried the find using just /sys/bus/usb./devices, it didn't work.
0
 
for_yanCommented:

Why not start with

/sys/bus/usb/devices/  

- would that part be stable?
0
 
for_yanCommented:
You had some dot befiore devioces ?
0
 
Elena QuinnAuthor Commented:
That was a typo - but I typed it correctly on the Linux system.  Is there a find command that would work for that?  I'm not that familiar with 'find'.
0
 
for_yanCommented:
find should work although its syntax may be a little bit mor complex
chek with

man find

I'm not sure you want put underscore there and maybe some other things
0
 
CEHJCommented:
What about Runtime.exec of lsusb?
0
 
for_yanCommented:
You still may try traversing directly from Java as I showed above.
It probably more stratight forward than to go to system and easier to deal with that than with find - you can use
easier some features of the filename - say three-character length, or maybe something else
0
 
Elena QuinnAuthor Commented:
OK, I added the following at line 90 of Test2.java to see what files are being found by the class.

files = dir.listFiles();
for (int i=0; i<files.length; i++){
    System.out.println(files[i].getName());
}

Open in new window


Test2 is finding the 'sde' folder, but for some reason not returning it when the filter is used.  So my problem appears to be with the filter that starts on line 51 of Test2.java.  Can someone take a look and let me know what might be the problem?
0
 
CEHJCommented:
Is 'block file found' getting printed?
0
 
CEHJCommented:
And if it *is* getting found, then http:#35263144 will be a lot easier. You might have to start searching  from a path further up the tree, e.g. /sys/bus/usb/devices
0
 
Elena QuinnAuthor Commented:
No - 'block file found' is not getting printed.
0
 
CEHJCommented:
Then if the first statement is printed, it's probably hidden (f.isHidden returns true)

What do you get from the command i recommended?
0
 
Elena QuinnAuthor Commented:
Hi CEHJ,

I tested whether the directory is hidden and it is not.   I modified the code again to basically not use the filter and put in my own filter (sort of).  Anyway, it's working.  I would like to learn why the filter doesn't work since I'm using the same criteria.  This makes no sense.

Here is what is now working:
files = dir.listFiles();
		for (int i=0; i<files.length; i++){
			System.out.println(files[i].getName());
			if (files[i].getName().startsWith("sd")){
				System.out.println(files[i].getName() + " is a match");
				m_blockFile = files[i];
				m_stopper = true;
				return;
			}
		}
		// the below code with the filter wasn't working on Slackware 13, so I'm going the long way.
	        //files = dir.listFiles(ffName);
	        //if (files != null && files.length > 0) {
		//		m_blockFile = files[0];
	        //    System.out.println("File found:" + m_blockFile.getPath());
	        //    m_stopper = true;
	        //    return;
	        //}

Open in new window

0
 
Elena QuinnAuthor Commented:
I was really looking for why the code I had wasn't working as opposed to another way of doing this, since I would have had to do a lot of rewriting if I had to use another method, like fdisk or find.

I would still like to know why the filter didn't work.  Is it the way I had it set up?  Any education on that would be appreciated.  For now, I have a work-around, so thanks to everyone.
0
 
CEHJCommented:
>>since I would have had to do a lot of rewriting if I had to use another method, like fdisk or find.

No, it would have been a few lines of code (which is why i suggested it)

Please post the *exact code* that was failing, after verifying it still fails
0
 
Elena QuinnAuthor Commented:
CEHJ,

I posted the entire code files with the original question.  NewTest2.java contains the filter starting at line 51.  Then the filter is used at line 90.  To make it work, I commented out the code from line 90 to line 96 and inserted the code above.

Also, I never got the find to work from /sys/bus/usb/devices  I tried using:

find /sys/bus/usb/devices -maxdepth 12 -name sd* 

Open in new window


but it didn't return anything.
0
 
CEHJCommented:
>>find /sys/bus/usb/devices -maxdepth 12 -name sd*

is not the command i gave you. That should be

find /sys/bus/usb/devices -maxdepth 12 -name sd\*

or

find /sys/bus/usb/devices -maxdepth 12 -name 'sd* '
0
 
Elena QuinnAuthor Commented:
Sorry CEHJ, both ways return me right back to the command prompt without displaying anything.  Maybe it's the OS version?
0
 
CEHJCommented:
Check  your method out.

a. any decent program should use a logging framework
b. methods should have only one exit point or they become difficult to  maintain:


/**

     * We want to only include certain directores-- because sybolic links makes things messy. Let's avoid symlinks.

     */

    private boolean directoryList(File _f) {

	String strName = _f.getName();

	boolean result = false;



	// look through all these types

	if(strName.length() >= 4 && strName.substring(0,4).equals("host")) {

	    result = true;

	}

	if(strName.length() >= 6 && strName.substring(0,6).equals("target")) {

	    result =  true;

	}

	if(strName.length() >= 5 && strName.substring(0,5).equals("block")) {

	    result =  true;

	}



	// basically, we're looking through all directories that begin with a number e.g. "1-1"

	try {

	    int i = Integer.parseInt(strName.substring(0,1));

	    result =  true;

	} catch(NumberFormatException nfe) {

	    result =  false;

	}

	System.out.printf("Returning %b for name %s in directory filter\n", result, strName);

	return result;

    }

Open in new window

0
 
Elena QuinnAuthor Commented:
My workaround fixed the problem, but it didn't really answer the question of why it wasn't working in the first place.  CEHJ tried very hard to help me, but I think we were thinking along different lines.  Anyway, it got me thinking and that resulted in the fix.
0
 
CEHJCommented:
:)

What happened when you ran http:#35285332 ?
0
 
Elena QuinnAuthor Commented:
That part was working because it was searching the 'block' directory.  I just couldn't get the filter to return the 'sd*' that was inside it.  I still don't know why the filter didn't work.  
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Cloud Class® Course: CompTIA Cloud+

The CompTIA Cloud+ Basic training course will teach you about cloud concepts and models, data storage, networking, and network infrastructure.

  • 12
  • 10
  • 6
Tackle projects and never again get stuck behind a technical roadblock.
Join Now