using glob() to search a drive

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
User avatar
batfastad
Forum Contributor
Posts: 433
Joined: Tue Mar 30, 2004 4:24 am
Location: London, UK

using glob() to search a drive

Post by batfastad »

Hi

I've been trying to get the function glob() to run recursively so I can return a list of files matching my search criteria.

The files I want to search are all on I:\files\ (i'm using windows xp sp1)

And in my search box on the page I want to just type in a string, and return a list of files or folders that contain that string in the name.
The problem I'm having is that I need it to search through sub-folders, and sub-folders of those as well.

How can I do this?

Is using glob() a practical way to search through files using PHP?
User avatar
Burrito
Spockulator
Posts: 4715
Joined: Wed Feb 04, 2004 8:15 pm
Location: Eden, Utah

Post by Burrito »

you could do it with glob() and just determine if the item is a file or folder using is_file().

if it's a folder, then recurse that folder and do whatever you want within all of the subfolders.
User avatar
batfastad
Forum Contributor
Posts: 433
Joined: Tue Mar 30, 2004 4:24 am
Location: London, UK

Post by batfastad »

Ok that's fine, but how do I do the initial search?

I want to search all files and subfolders of I:\testfolder for an occurence of 'foo' in the file name.

I need the array to not only return files with foo in the title, but also folders with foo in the title.

Any ideas?
User avatar
Burrito
Spockulator
Posts: 4715
Joined: Wed Feb 04, 2004 8:15 pm
Location: Eden, Utah

Post by Burrito »

ummm try:

Code: Select all

$stuff = glob("i:\\testfolder\\*foo*");
User avatar
batfastad
Forum Contributor
Posts: 433
Joined: Tue Mar 30, 2004 4:24 am
Location: London, UK

Post by batfastad »

Ok I've got an almost solution to this.

using the example on the glob() manual page...

Code: Select all

/**
 * Recursive version of glob
 *
 * @return array containing all pattern-matched files.
 *
 * @param string $sDir      Directory to start with.
 * @param string $sPattern  Pattern to glob for.
 * @param int $nFlags      Flags sent to glob.
 */

function globr($sDir, $sPattern, $nFlags = NULL)
{
  $sDir = escapeshellcmd($sDir);

  // Get the list of all matching files currently in the
  // directory.

  $aFiles = glob("$sDir/$sPattern", $nFlags);

  // Then get a list of all directories in this directory, and
  // run ourselves on the resulting array.  This is the
  // recursion step, which will not execute if there are no
  // directories.

  foreach (glob("$sDir/*", GLOB_ONLYDIR) as $sSubDir)
  {
   $aSubFiles = globr($sSubDir, $sPattern, $nFlags);
   $aFiles = array_merge($aFiles, $aSubFiles);
  }

  // The array we return contains the files we found, and the
  // files all of our children found.

  return $aFiles;
}
It seems to work.
And work fast!

But it also adds many blank entries in the resulting array.
That's not too much of a problem as I will loop through the array a second time to display the results and strip out the unwanted lines.

There's one problem with this function though - the searches are case-sensitive.

Any idea how to make this function non case-sensitive?
User avatar
Burrito
Spockulator
Posts: 4715
Joined: Wed Feb 04, 2004 8:15 pm
Location: Eden, Utah

Post by Burrito »

since you're on windows, the case of the file name shouldn't matter when you go to call it to do whatever you want.

use strtolower() to change the names of the files/folder and your search text then perform your search.
User avatar
batfastad
Forum Contributor
Posts: 433
Joined: Tue Mar 30, 2004 4:24 am
Location: London, UK

Post by batfastad »

It does seem to matter

When I search for *Buster* it returns the results, but when I search for *buster* i get no results.
Also when I search for *BUster* I don't get any results.

I need to return results that match any case permutation.


In my code...

Code: Select all

/**
 * Recursive version of glob
 *
 * @return array containing all pattern-matched files.
 *
 * @param string $sDir      Directory to start with.
 * @param string $sPattern  Pattern to glob for.
 * @param int $nFlags      Flags sent to glob.
 */

function globr($sDir, $sPattern, $nFlags = NULL)
{
  $sDir = escapeshellcmd($sDir);

  // Get the list of all matching files currently in the
  // directory.

  $aFiles = glob("$sDir/$sPattern", $nFlags);

  // Then get a list of all directories in this directory, and
  // run ourselves on the resulting array.  This is the
  // recursion step, which will not execute if there are no
  // directories.

  foreach (glob("$sDir/*", GLOB_ONLYDIR) as $sSubDir)
  {
   $aSubFiles = globr($sSubDir, $sPattern, $nFlags);
   $aFiles = array_merge($aFiles, $aSubFiles);
  }

  // The array we return contains the files we found, and the
  // files all of our children found.

  return $aFiles;
}

$results = globr("I:/MP3", "*BUster*");
echo ("<pre>");
print_r ($results);
echo ("</pre>");
Where do I put the strtolower() function in my globr() function?


Thanks

Ben
User avatar
Burrito
Spockulator
Posts: 4715
Joined: Wed Feb 04, 2004 8:15 pm
Location: Eden, Utah

Post by Burrito »

ahh yes I see the problem now...for some reason I thought you were creating an array of all of the files then searching that array...guess I should've remembered this post from earlier this morning.

let me stew on this a bit, can't think right at the moment of how you could build your array with only those files for which you're searchign and ignore case...

one thing I KNOW you could do would be loop over all of the files and rename them to lower case, then when you call your globr function, use strtolower in your argument for the search string.

that's a round-about way of doing it and probably not the best solution, but it would definitely work for you.

as I said, I'll think a bit on how you could use glob and have it case insensitive for your primary argument.
User avatar
batfastad
Forum Contributor
Posts: 433
Joined: Tue Mar 30, 2004 4:24 am
Location: London, UK

Post by batfastad »

Thanks for taking the time to think this through.


I don't really fancy renaming all my files just to do this unfortunately.

I would have thought that there'd be a way to just ignore case.
None of the flags you can pass to glob() seem to do that.

I'll keep working on it!
User avatar
Burrito
Spockulator
Posts: 4715
Joined: Wed Feb 04, 2004 8:15 pm
Location: Eden, Utah

Post by Burrito »

I've just been chatting with D11 about this, not sure it can be done using glob to build your array initially with your pared down file list.

my suggestion: build an array using glob(i:\\myfolder\\*) and search against the array for your file names...

sorry I don't have another solution for you. If I have an epiphany tonight, I shall let you know. 8O
User avatar
batfastad
Forum Contributor
Posts: 433
Joined: Tue Mar 30, 2004 4:24 am
Location: London, UK

Post by batfastad »

Yeah I thought about just getting all the files into an array, then searching the array.

It's not the most efficient way - especially when there'll be 30,000 files in that array!, and growing.
Another problem I'm having with glob()
When using glob(i:\\myfolder\\*) I've found it's not returning items to the array that have an ampersand & in the file/folder name.

Is there a way round this?


Something that can't be done in PHP?
Blimey :lol:
User avatar
Burrito
Spockulator
Posts: 4715
Joined: Wed Feb 04, 2004 8:15 pm
Location: Eden, Utah

Post by Burrito »

you might be better suited to take a step back from glob() and use readdir() and loop over everyting within the folder using a while loop.

that should take care of your case issue too...
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

You know I'm not even sure how slow the readdir() method will be... Nobody can argue it's unreliable neither.

glob(), from what I have read is a very basic search method and you could probably write something much more powerful yourself, at the cost of losing speed (not sure what's with the ampersand issue though)...
Post Reply