PHP Doku:: Findet Dateinamen, die mit einem Muster übereinstimmen - function.glob.html

Verlauf / Chronik / History: (1) anzeigen

Sie sind hier:
Doku-StartseitePHP-HandbuchFunktionsreferenzDateisystemrelevante ErweiterungenDateisystemDateisystem-Funktionenglob

Ein Service von Reinhard Neidl - Webprogrammierung.

Dateisystem-Funktionen

<<fwrite

is_dir>>

glob

(PHP 4 >= 4.3.0, PHP 5)

globFindet Dateinamen, die mit einem Muster übereinstimmen

Beschreibung

array glob ( string $pattern [, int $flags = 0 ] )

glob() findet Dateipfade, die mit dem angegebenen Muster pattern übereinstimmen. Die Übereinstimmung wird nach den gleichen Regeln geprüft, wie in der glob()-Funktion der C-Bibliothek und entspricht weitgehend den Regeln in den üblichen Kommandozeilen-Shells.

Parameter-Liste

pattern

Das Suchmuster. Parameter- und Tilde-Ersetzung findet nicht statt.

flags

Mögliche Flags:

  • GLOB_MARK - Fügt jedem zurückgegebenen Verzeichnis einen Slash hinzu
  • GLOB_NOSORT - Gibt Dateinamen unsortiert in der Reihenfolge ihrer Verzeichniseinträge zurück
  • GLOB_NOCHECK - Gibt das Suchmuster zurück, wenn keine übereinstimmende Dateinamen gefunden wurden
  • GLOB_NOESCAPE - Backslashes maskieren keine Metazeichen
  • GLOB_BRACE - {a,b,c} prüft auf 'a', 'b', oder 'c'
  • GLOB_ONLYDIR - Gibt nur übereinstimmende Verzeichnisnamen zurück
  • GLOB_ERR - Anhalten bei Lesefehlern (wie nicht-lesbaren Verzeichnis), standardmäßig werden Fehler ignoriert

Rückgabewerte

Gibt ein Array mit den übereinstimmenden Datei- und Verzeichnisnamen zurück. Wenn keine Treffer gefunden wurden, wird ein leeres Array zurückgegeben und im Fehlerfall FALSE.

Hinweis:

Auf manchen Systemen ist es nicht möglich, zwischen einer leeren Ergebnismenge und einem aufgetretenen Fehler zu unterscheiden.

Changelog

Version Beschreibung
5.1.0 GLOB_ERR wurde hinzugefügt
4.3.3 GLOB_ONLYDIR ist nun auch unter Windows und anderen Systemen, die nicht die GNU-C-Bibliothek benutzen

Beispiele

Beispiel #1 Einfacher Ersatz von opendir() etc.

<?php
foreach (glob("*.txt") as $filename) {
    echo 
"$filename - Größe: " filesize($filename) . "\n";
}
?>

Das oben gezeigte Beispiel erzeugt eine ähnliche Ausgabe wie:

funclist.txt - Größe: 44686
funcsummary.txt - Größe: 267625
quickref.txt - Größe: 137820

Anmerkungen

Hinweis: Diese Funktion kann nicht mit entfernten Dateien arbeiten, da der Zugriff auf die Datei, die bearbeitet werden soll, über das Dateisystem des Servers möglich sein muss.

Hinweis: Diese Funktion ist nicht auf allen Systemen verfügbar (z.B. nicht auf alten Sun-OS-Versionen).

Hinweis: Das GLOB_BRACE-Flag ist auf einigen nicht-GNU-Systemen (wie Solaris) nicht verfügbar.

Siehe auch

  • opendir() - Öffnen eines Verzeichnis-Handles
  • readdir() - Liest einen Eintrag aus einem Verzeichnis-Handle
  • closedir() - Schließen eines Verzeichnis-Handles
  • fnmatch() - Match filename against a pattern


72 BenutzerBeiträge:
- Beiträge aktualisieren...
reinhard at neidl.net
22.11.2010 21:50
<?php
//A function to convert the glob pattern in a case insensitive version:
//SHORT: make glob() case insensitiv.
//sample call:
//$filelist =  glob( '/path/*/'.globistr('*.PHP') ); //all *.php files in subfolders

//sample call:
//$filelist =  glob( dirname(__FILE__).'/'.globistr('*.JPG') );
//$filelist =  array_merge($filelist,glob( dirname(__FILE__).'/'.globistr('*.JPEG') ));
//$filelist =  array_merge($filelist,glob( dirname(__FILE__).'/'.globistr('*.gif') ));

//multibyte sample:
//$test = "mĄkAÉÁÇÚÍÑАвстрал";
//$pattern = globistr($test,'UTF-8');
//RESULT: pattern:[mM][ąĄ][kK][aA]...

function globistr($string = '', $mbEncoding = ''/*optional e.g.'UTF-8'*/){
   
//returns a case insensitive Version of the searchPattern for glob();
    // e.g.: globistr('./*.jpg') => './*.[jJ][pP][gG]'
    // e.g.: glob(dirname(__FILE__).'/'.globistr('*.jpg')) => '/.../*.[jJ][pP][gG]'
   
    // known problems: globistr('./[abc].jpg') => FALSE:'./[[aA][bB][cC]].[jJ][pP][gG]'
    //(Problem: existing Pattern[abc] will be overwritten)
    // known solution: './[abc].'.globistr('jpg') => RIGHT: './[abc].[jJ][pP][gG]'
    //(Solution: globistr() only caseSensitive Part, not everything)
   
$return = "";
    if(
$mbEncoding !== ''){ //multiByte Version
       
$string = mb_convert_case($string,MB_CASE_LOWER,$mbEncoding);
    }
    else{
//standard Version (not multiByte,default)
       
$string = strtolower($string);
    }
   
$mystrlen = strlen($string);
    for(
$i=0;$i<$mystrlen;$i++){
        if(
$mbEncoding !== ''){//multiByte Version
           
$myChar = mb_substr($string,$i,1,$mbEncoding);
           
//$myUpperChar = mb_strtoupper($myChar,$mbEncoding);
           
$myUpperChar = mb_convert_case($myChar,MB_CASE_UPPER,$mbEncoding);
        }else{
           
$myChar = substr($string,$i,1);
           
$myUpperChar = strtoupper($myChar);
        }
        if(
$myUpperChar !== $myChar){ //there is a lower- and upperChar, / Char is case sentitive
           
$return .= '['.$myChar.$myUpperChar.']'; //adding both Versions : [xX]
       
}else{//only one case Version / Char is case insentitive
           
$return .= $myChar; //adding '1','.','*',...
       
}
    }
    return
$return;
}

?>
arvin at sudocode dot net
20.11.2010 17:20
I made this non-recursive implementation for recursive glob with a depth parameter. The search is done breadth-first and specifying -1 for the depth means no limit.
<?php
function bfglob($path, $pattern = '*', $flags = 0, $depth = 0) {
       
$matches = array();
       
$folders = array(rtrim($path, DIRECTORY_SEPARATOR));
       
        while(
$folder = array_shift($folders)) {
           
$matches = array_merge($matches, glob($folder.DIRECTORY_SEPARATOR.$pattern, $flags));
            if(
$depth != 0) {
               
$moreFolders = glob($folder.DIRECTORY_SEPARATOR.'*', GLOB_ONLYDIR);
               
$depth   = ($depth < -1) ? -1: $depth + count($moreFolders) - 2;
               
$folders = array_merge($folders, $moreFolders);
            }
        }
        return
$matches;
    }
?>

Parameters:
$path   - path of folder to search
$pattern- glob pattern
$flags  - glob flags
$depth  - 0 for current folder only, 1 to descend 1 folder down, and so on. -1 for no limit.
peter dot adrianov at gmail dot com
14.05.2010 13:29
Non-recursive search files, proceeding down directory tree.

<?php
function scandir_through($dir)
{
   
$items = glob($dir . '/*');

    for (
$i = 0; $i < count($items); $i++) {
        if (
is_dir($items[$i])) {
           
$add = glob($items[$i] . '/*');
           
$items = array_merge($items, $add);
        }
    }

    return
$items;
}
?>
BigueNique at yahoo dot ca
8.05.2010 20:45
Here is the function array_prepend() used by my latest post of safe_glob().

<?php
/**
 * Prepends $string to each element of $array
 * If $deep is true, will indeed also apply to sub-arrays
 * @author BigueNique AT yahoo DOT ca
 * @since 080324
 */
function array_prepend($array, $string, $deep=false) {
    if(empty(
$array)||empty($string)) return $array;
    foreach(
$array as $key => $element)
        if(
is_array($element))
            if(
$deep)
               
$array[$key] = array_prepend($element,$string,$deep);
            else
               
trigger_error('array_prepend: array element',E_USER_WARNING);
        else
           
$array[$key] = $string.$element;
    return
$array;
   
}
?>
BigueNique at yahoo dot ca
20.04.2010 9:15
Since I discovered my safe_glob() implementation has been widely used by other folks and it has evolved quite a bit since the time I first posted it, here is an updated version. It has proven quite handy and robust on my side. That being said, use it at your own risk!

I added a few extra option constants that can make some common operations a breeze. For the rest, the code speaks for itself.

/**#@+
 * Extra GLOB constant for safe_glob()
 */
define('GLOB_NODIR',256);
define('GLOB_PATH',512);
define('GLOB_NODOTS',1024);
define('GLOB_RECURSE',2048);
/**#@-*/

/**
 * A safe empowered glob().
 *
 * Function glob() is prohibited on some server (probably in safe mode)
 * (Message "Warning: glob() has been disabled for security reasons in
 * (script) on line (line)") for security reasons as stated on:
 * http://seclists.org/fulldisclosure/2005/Sep/0001.html
 *
 * safe_glob() intends to replace glob() using readdir() & fnmatch() instead.
 * Supported flags: GLOB_MARK, GLOB_NOSORT, GLOB_ONLYDIR
 * Additional flags: GLOB_NODIR, GLOB_PATH, GLOB_NODOTS, GLOB_RECURSE
 * (not original glob() flags)
 * @author BigueNique AT yahoo DOT ca
 * @updates
 * - 080324 Added support for additional flags: GLOB_NODIR, GLOB_PATH,
 *   GLOB_NODOTS, GLOB_RECURSE
 */
function safe_glob($pattern, $flags=0) {
    $split=explode('/',str_replace('\\','/',$pattern));
    $mask=array_pop($split);
    $path=implode('/',$split);
    if (($dir=opendir($path))!==false) {
        $glob=array();
        while(($file=readdir($dir))!==false) {
            // Recurse subdirectories (GLOB_RECURSE)
            if( ($flags&GLOB_RECURSE) && is_dir($file) && (!in_array($file,array('.','..'))) )
                $glob = array_merge($glob, array_prepend(safe_glob($path.'/'.$file.'/'.$mask, $flags),
                    ($flags&GLOB_PATH?'':$file.'/')));
            // Match file mask
            if (fnmatch($mask,$file)) {
                if ( ( (!($flags&GLOB_ONLYDIR)) || is_dir("$path/$file") )
                  && ( (!($flags&GLOB_NODIR)) || (!is_dir($path.'/'.$file)) )
                  && ( (!($flags&GLOB_NODOTS)) || (!in_array($file,array('.','..'))) ) )
                    $glob[] = ($flags&GLOB_PATH?$path.'/':'') . $file . ($flags&GLOB_MARK?'/':'');
            }
        }
        closedir($dir);
        if (!($flags&GLOB_NOSORT)) sort($glob);
        return $glob;
    } else {
        return false;
    }   
}

/**
 * A better "fnmatch" alternative for windows that converts a fnmatch
 * pattern into a preg one. It should work on PHP >= 4.0.0.
 * @author soywiz at php dot net
 * @since 17-Jul-2006 10:12
 */
if (!function_exists('fnmatch')) {
    function fnmatch($pattern, $string) {
        return @preg_match('/^' . strtr(addcslashes($pattern, '\\.+^$(){}=!<>|'), array('*' => '.*', '?' => '.?')) . '$/i', $string);
    }
}
ottodenn at gmail dot com
1.02.2010 11:18
just a quick one:

get all dirs, without files:
<?php
$dirs
= array_filter(glob($path.'*'), 'is_dir');
?>
dragos dot rusu at ymail dot com
11.11.2009 9:52
Glob function doesn't return the hidden files (including ".*" files). PHP5 RecursiveIterator can be used for iterating through directories recursively.
tailinchu[at]gmail[dot]com
18.10.2009 3:50
here is a quick fix when nothing matches, glob will return false

<?php $files=glob('*.txt')?glob('*.txt'):array(); ?>

now you are able to use array function to $files.
wang yun
22.09.2009 15:00
A function to quickly remove a directory (works in seconds for a hundred thousand files)

<?php
/**
 * Remove the directory and its content (all files and subdirectories).
 * @param string $dir the directory name
 */
function rmrf($dir) {
    foreach (
glob($dir) as $file) {
        if (
is_dir($file)) {
           
rmrf("$file/*");
           
rmdir($file);
        } else {
           
unlink($file);
        }
    }
}
?>
uramihsayibok, gmail, com
5.08.2009 0:38
Those of you with PHP 5 don't have to come up with these wild functions to scan a directory recursively: the SPL can do it.

<?php

$dir_iterator
= new RecursiveDirectoryIterator("/path");
$iterator = new RecursiveIteratorIterator($dir_iterator, RecursiveIteratorIterator::SELF_FIRST);
// could use CHILD_FIRST if you so wish

foreach ($iterator as $file) {
    echo
$file, "\n";
}

?>

Not to mention the fact that $file will be an SplFileInfo class, so you can do powerful stuff really easily:

<?php

$size
= 0;
foreach (
$iterator as $file) {
    if (
$file->isFile()) {
        echo
substr($file->getPathname(), 27) . ": " . $file->getSize() . " B; modified " . date("Y-m-d", $file->getMTime()) . "\n";
       
$size += $file->getSize();
    }
}

echo
"\nTotal file size: ", $size, " bytes\n";

?>

\Luna\luna.msstyles: 4190352 B; modified 2008-04-13
\Luna\Shell\Homestead\shellstyle.dll: 362496 B; modified 2006-02-28
\Luna\Shell\Metallic\shellstyle.dll: 362496 B; modified 2006-02-28
\Luna\Shell\NormalColor\shellstyle.dll: 361472 B; modified 2006-02-28
\Luna.theme: 1222 B; modified 2006-02-28
\Windows Classic.theme: 3025 B; modified 2006-02-28

Total file size: 5281063 bytes
endiku
29.07.2009 17:47
For those who need to recursively search a directory tree and cannot or wish not to call a function within itself here is another suggestion.

I tried the previously suggested listdirs_safe() and it didn't seem to find all subfolders in a directory tree.

There are two variations on the same theme.

Single Array.
<?php
$dir
='/dir';
while(
$dirs = glob($dir . '/*', GLOB_ONLYDIR)) {
 
$dir .= '/*';
  if(!
$d) {
    
$d=$dirs;
   } else {
     
$d=array_merge($d,$dirs);
   }
}
?>

Multiple arrays.
<?php
$n
=0;
$dir ='/dir';
while(
$dirs = glob($dir . '/*', GLOB_ONLYDIR)) {
 
$dir .= '/*';
  if(!
$d) {
    
$d=$dirs;
   } else {
    
$d[$n]=$dirs;
   }
 
$n++;
}
?>

This will result in the glob looping via "dir/*/*/*/*.." until it is no longer finding a directory structure.
nuntius
6.07.2009 19:10
First off, it's nice to see all of the different takes on this. Thanks for all of the great examples.

Fascinated by the foreach usage I was curious how it might work with a for loop. I found that glob was well suited for this, especially compared to opendir.  The for loop is always efficient when you want to protect against a potential endless loop.

$dir=$_SERVER['DOCUMENT_ROOT']."/test/directory_listing/test";
    echo $dir;
    $filesArray=glob($dir."/*.*");   
   
    $line.="<pre>";
    $line.=print_r($filesArray, true);
    $line.="</pre>";
    $line.="<hr>";
   
    for($i=0;$i<count($filesArray);$i++) {
        $line.=key($filesArray)." - ";   
        $line.=$filesArray[$i]."<br/>";
         next($filesArray);
    }

    echo $line;

Note that I pulled the glob array keys if you should need them.

Also you can tweak it for searches with something like this... (case sensitive)

$search_names="Somedocname";
$filesArray=glob($dir."/".$search_names."*.*");   
   
Enjoy!
sven at NOSPAM dot sven dot globalunix dot org
11.06.2009 18:22
If you want to use wildcard expressions (like they are used by glob() ) to search on strings, you can use this function:

<?php   
function match_wildcard( $wildcard_pattern, $haystack ) {
  
$regex = str_replace(
     array(
"\*", "\?"), // wildcard chars
    
array('.*','.'),   // regexp chars
    
preg_quote($wildcard_pattern)
   );

   return
preg_match('/^'.$regex.'$/is', $haystack);
}

$test = "foobar and blob\netc.";
var_dump(
   
match_wildcard('foo*', $test),      // TRUE
   
match_wildcard('bar*', $test),      // FALSE
   
match_wildcard('*bar*', $test),     // TRUE
   
match_wildcard('**blob**', $test),  // TRUE
   
match_wildcard('*a?d*', $test),     // TRUE
   
match_wildcard('*etc**', $test)     // TRUE
);
?>
r dot hartung at roberthartung dot de
4.05.2009 9:34
You can use multiple asterisks with the glob() - function.

Example:

<?php
  $paths
= glob('my/*/dir/*.php');
?>

$paths will contains paths as following examples:

- my/1/dir/xyz.php
- my/bar/dir/bar.php
- my/bar/dir/foo.php
crayonviolent at phpfreaks dot com
17.01.2009 8:50
Since I feel this is rather vague and non-helpful, I thought I'd make a post detailing the mechanics of the glob regex.

glob uses two special symbols that act like sort of a blend between a meta-character and a quantifier.  These two characters are the * and ?

The ? matches 1 of any character except a /
The * matches 0 or more of any character except a /

If it helps, think of the * as the pcre equivalent of .* and ? as the pcre equivalent of the dot (.)

Note: * and ? function independently from the previous character. For instance, if you do glob("a*.php") on the following list of files, all of the files starting with an 'a' will be returned, but * itself would match:

a.php // * matches nothing
aa.php // * matches the second 'a'
ab.php // * matches 'b'
abc.php // * matches 'bc'
b.php // * matches nothing, because the starting 'a' fails
bc.php // * matches nothing, because the starting 'a' fails
bcd.php // * matches nothing, because the starting 'a' fails

It does not match just a.php and aa.php as a 'normal' regex would, because it matches 0 or more of any character, not the character/class/group before it.

Executing glob("a?.php") on the same list of files will only return aa.php and ab.php because as mentioned, the ? is the equivalent of pcre's dot, and is NOT the same as pcre's ?, which would match 0 or 1 of the previous character.

glob's regex also supports character classes and negative character classes, using the syntax [] and [^]. It will match any one character inside [] or match any one character that is not in [^].

With the same list above, executing

glob("[ab]*.php) will return (all of them):
a.php  // [ab] matches 'a', * matches nothing
aa.php // [ab] matches 'a', * matches 2nd 'a'
ab.php // [ab] matches 'a', * matches 'b'
abc.php // [ab] matches 'a', * matches 'bc'
b.php // [ab] matches 'b', * matches nothing
bc.php // [ab] matches 'b', * matches 'c'
bcd.php // [ab] matches 'b', * matches 'cd'

glob("[ab].php") will return a.php and b.php

glob("[^a]*.php") will return:
b.php // [^a] matches 'b', * matches nothing
bc.php // [^a] matches 'b', * matches 'c'
bcd.php // [^a] matches 'b', * matches 'cd'

glob("[^ab]*.php") will return nothing because the character class will fail to match on the first character.

You can also use ranges of characters inside the character class by having a starting and ending character with a hyphen in between.  For example, [a-z] will match any letter between a and z, [0-9] will match any (one) number, etc..

glob also supports limited alternation with {n1, n2, etc..}.  You have to specify GLOB_BRACE as the 2nd argument for glob in order for it to work.  So for example, if you executed glob("{a,b,c}.php", GLOB_BRACE) on the following list of files:

a.php
b.php
c.php

all 3 of them would return.  Note: using alternation with single characters like that is the same thing as just doing glob("[abc].php").  A more interesting example would be glob("te{xt,nse}.php", GLOB_BRACE) on:

tent.php
text.php
test.php
tense.php

text.php and tense.php would be returned from that glob.

glob's regex does not offer any kind of quantification of a specified character or character class or alternation.  For instance, if you have the following files:

a.php
aa.php
aaa.php
ab.php
abc.php
b.php
bc.php

with pcre regex you can do ~^a+\.php$~ to return

a.php
aa.php
aaa.php

This is not possible with glob.  If you are trying to do something like this, you can first narrow it down with glob, and then get exact matches with a full flavored regex engine.  For example, if you wanted all of the php files in the previous list that only have one or more 'a' in it, you can do this:

<?php
   $list
= glob("a*.php");
   foreach (
$list as $l) {
      if (
preg_match("~^a+\.php$~",$file))
        
$files[] = $l;
   }
?>

glob also does not support lookbehinds, lookaheads, atomic groupings, capturing, or any of the 'higher level' regex functions.

glob does not support 'shortkey' meta-characters like \w or \d.
php [spat] hm2k.org
25.11.2008 11:39
<?php
// $Id: rglob.php,v 1.0 2008/11/24 17:20:00 hm2k Exp $

/**
 * Recursive glob()
 */

/**
 * @param int $pattern
 *  the pattern passed to glob()
 * @param int $flags
 *  the flags passed to glob()
 * @param string $path
 *  the path to scan
 * @return mixed
 *  an array of files in the given path matching the pattern.
 */

function rglob($pattern='*', $flags = 0, $path='')
{
   
$paths=glob($path.'*', GLOB_MARK|GLOB_ONLYDIR|GLOB_NOSORT);
   
$files=glob($path.$pattern, $flags);
    foreach (
$paths as $path) { $files=array_merge($files,rglob($pattern, $flags, $path)); }
    return
$files;
}

/* example usage: */
chdir('../');
var_export(rglob('*.php'));

?>
carlos dot lage at nospam at foo dot bar at gmail dot com
18.10.2008 3:18
I lost hours looking for the solution for this problem.
glob() wasn't eating up my directory names (stuff like "foobar[]"), and I searched online for some hours, I tried preg_quote to no avail.

I finally found the proper way to escape stuff in glob() in an obscure Python mailing list:

<?php
preg_replace
('/(\*|\?|\[)/', '[$1]', $dir_path);
?>

If you want to add a directory path before your pattern, you should do it like this:

<?php
glob
(preg_replace('/(\*|\?|\[)/', '[$1]', $dir_path).'*.txt');
?>
preg_quote WILL NOT work in all cases (if any).
vidmantas dot norkus at neo dot lt
22.08.2008 15:00
My version of recursive glob
<?php
function all_files($dir)
{
   
$files = Array();
   
$file_tmp= glob($dir.'*',GLOB_MARK | GLOB_NOSORT);

    foreach(
$file_tmp as $item){
        if(
substr($item,-1)!=DIRECTORY_SEPARATOR)
           
$files[] = $item;
        else
           
$files = array_merge($files,all_files($item));
    }

    return
$files;
}
?>
hazemaboali at gmail dot com
22.05.2008 18:02
<?php

FUNCTION glob2($i)
{
 
$input = explode('/',$i); $count = count($input);
  if(
$count>=2)
  {
 
$i = 0;
  while(++
$i < $count)
  { if(
is_dir($input[$i-1]))
   
$directory[] = $input[$i-1];
  }

 
$dir = join('/',$directory);
  }else{
     
$dir = './';
  }

 
$db = opendir($dir);
 
$output = array();
 while((
$file = readdir($db))!= false)
  {
     if(
preg_match("#".$input[$count-1]."#",$file))
    
$output[] = $file;
  }
  @
closedir($db);

 return
$output;
}

$dir = glob2("upload/.*\.php");

print_r($dir);

?>
heavyraptor at gmail dot com
19.05.2008 13:56
glob() (array_sum() and array_map() in fact too) can be very useful if you want to calculate the sum of all the files' sizes located in a directory:

<?php
$bytes
= array_sum(array_map('filesize',glob('*')));
?>

Unfortunately there's no way to do this recursively, using glob() (as far as I know).
miah [at] miahs [dot] de
17.05.2008 22:38
You should use preg_quote every time you want to add a path to an directory.

Use it like this:

<?php

$dir
= './mydir/[with]/special/.chars/';
$file = '[a-z]+\.txt';

$files = glob( preg_quote( $dir, DIRECTORY_SEPARATOR ) . $file );

if(
$files !== false && count($files) != 0)
{
   
// Do something with the files
}

?>

Reason:

Special chars like [ or . will match in regular expressions so "/dir/[special]/*.txt" will match on all files in the dirs

/dir/s/, /dir/p/, /dir/e/, /dir/c/, /dir/i/, /dir/a/, /dir/l/

I hope i could help.

MFG Miah :)
pope at q dot com
24.04.2008 3:08
alan at ridersite dot org 18-Mar-2007 03:26 -- Stated '*.*' is the same as '*' -- This is not true as * alone will return directories too and *.* will only return files with an extension such as .pdf or .doc or .php.
alan at synergymx dot com
15.04.2008 21:08
Here is a function that returns specific files in an array, with all of the details. Includes some basic garbage checking.

Variables

$source_folder // the location of your files
$ext // file extension you want to limit to (i.e.: *.txt)
$sec // if you only want files that are at least so old.

The function

function glob_files($source_folder, $ext, $sec, $limit){
    if( !is_dir( $source_folder ) ) {
        die ( "Invalid directory.\n\n" );
    }
   
    $FILES = glob($source_folder."\*.".$ext);
    $set_limit    = 0;
   
    foreach($FILES as $key => $file) {
   
        if( $set_limit == $limit )    break;
       
        if( filemtime( $file ) > $sec ){
       
            $FILE_LIST[$key]['path']    = substr( $file, 0, ( strrpos( $file, "\\" ) +1 ) );
            $FILE_LIST[$key]['name']    = substr( $file, ( strrpos( $file, "\\" ) +1 ) );   
            $FILE_LIST[$key]['size']    = filesize( $file );
            $FILE_LIST[$key]['date']    = date('Y-m-d G:i:s', filemtime( $file ) );
            $set_limit++;
       
        }
       
    }
    if(!empty($FILE_LIST)){
        return $FILE_LIST;
    } else {
        die( "No files found!\n\n" );
    }
}

So....

$source_folder = "c:\temp\my_videos";
$ext = "flv"; // flash video files
$sec = "7200"; // files older than 2 hours
$limit = 2;

print_r(glob_files($source_folder, $ext, $sec, $limit));

Would return:

Array
(
    [0] => Array
        (
            [path] => c:\temp\my_videos\
            [name] => fluffy_bunnies.flv
            [size] => 21160480
            [date] => 2007-10-30 16:48:05
        )

    [1] => Array
        (
            [path] => c:\temp\my_videos\
            [name] => synergymx.com.flv
            [size] => 14522744
            [date] => 2007-10-25 15:34:45
        )
eric at muyser dot com
11.04.2008 17:31
As a follow up to recursively determining all paths (by viajy at yoyo dot org) and opendir being faster than glob (by Sam Yong - hellclanner at live [dot] com).

The list all dirs code didn't seem to work, at least on my server (provided by parazuce [at] gmail [dot] com).

I needed a function to create an unlimited multidimensional array, with the names of the folders/files intact (no realpath's, although that is easily possible). This is so I can simply loop through the array, create an expandable link on the folder name, with all the files inside it.

This is the correct way to recurse I believe (no static, return small arrays to build up the multidimensional array), and includes a check for files/folders beginning with dots.

// may need modifications

function list_files($path)
{
    $files = array();
   
    if(is_dir($path))
    {
        if($handle = opendir($path))
        {
            while(($name = readdir($handle)) !== false)
            {
                if(!preg_match("#^\.#", $name))
                if(is_dir($path . "/" . $name))
                {
                    $files[$name] = list_files($path . "/" . $name);
                }
                else
                {
                    $files[] = $name;
                }
            }
           
            closedir($handle);
        }
    }

    return $files;
}

print_r(list_files("/path/to/folder"));

// example usage

function list_html($list)
{
    $html = "";
   
    foreach($list as $folder => $file)
    {
        if(is_array($list[$folder]))
        {
            $html .= "> (folder) " . $folder . "<br>";
            $html .= list_html($list[$folder]);
        }
        else
        {
            $html .= " (file) " . $file . "<br>";
        }
    }
   
    return $html;
}

echo list_html(list_files("/path/to/folder"));
parazuce [at] gmail [dot] com
31.03.2008 3:47
As a response to a post by viajy at yoyo dot org on 10-Feb-2007 04:50, he posted the following code:
<?php
function listdirs($dir) {
    static
$alldirs = array();
   
$dirs = glob($dir . '/*', GLOB_ONLYDIR);
    if (
count($dirs) > 0) {
        foreach (
$dirs as $d) $alldirs[] = $d;
    }
    foreach (
$dirs as $dir) listdirs($dir);
    return
$alldirs;
}
?>

It is not best practice to use recursive functions like that, so I wrote a safe (non-recursive) function below:

<?php
function listdirs_safe($start)
{
   
$dir  = $start;
   
$dirs = array();
   
$next = 0;

    while (
true)
    {
       
$_dirs = glob($dir.'/*', GLOB_ONLYDIR);

        if (
count($_dirs) > 0)
        {
            foreach (
$_dirs as $key => $_dir)
               
$dirs[] = $_dir;
        }
        else
            break;
           
       
$dir = $dirs[$next++];
    }
   
    return
$dirs;
}
?>

Example:

print_r(listdirs_safe('*'));

Output:
Array
(
    [0] => Dummy folder/Dummy folder 2
    [1] => Dummy folder/Dummy folder 2/Dummy Folder 3
    [2] => Dummy folder/Dummy folder 2/Dummy Folder 3/4
    [3] => Dummy folder/Dummy folder 2/Dummy Folder 3/Dummy folder 4
    [4] => Dummy folder/Dummy folder 2/Dummy Folder 3/4/5
)
bisqwit at iki dot fi
2.03.2008 0:46
Pomle.com wrote:
> Here's a function that behaves as a recursive glob(). It does
> rely on shell command find, but works like a charm.
> function glob_rec($pattern, $path) {
>    return explode("\n", shell_exec("find $path -name $pattern"));
> }

Do note that this command has a security hole.
If the $path or $pattern given includes special characters, for example a command substitution such as "`rm index.php`", the shell will process it and execute that command.

You can fix the problem by either escaping the characters properly (use shell_escape) or by writing a function that actually calls glob(), or opendir()/readdir()/closedir(), recursively.
Pomle.com
7.02.2008 18:15
Here's a function that behaves as a recursive glob(). It does rely on shell command find, but works like a charm.

function glob_rec($pattern, $path) {
    return explode("\n", shell_exec("find $path -name $pattern"));
}
pecoes at web dot de
27.01.2008 18:46
As mentioned below, characters like [ and ] cause problems and need to be escaped with a backslash. But it's *not* enough to escape them in the pattern itself! If they appear in the path to the working directory, glob() also fails!

So, if this fails:

glob('*.txt');

Try:

glob(preg_quote(getcwd() . DIRECTORY_SEPARATOR) . '*.txt');
sean at syosoft dot com
16.11.2007 11:48
Run your directory + "file pattern" through preg_quote to get around [ ] / etc issues...glob uses pattern matching.
josh at servebyte dot com
23.07.2007 14:55
To:  martinlarsen at bigfoot dot com (14-Jun-2007 01:13)

[quote]
glob() does not work if the path contains brackets "[" and "]".

For example, this will make it fail:

$files = glob("[myfolder]/*.txt");

No error is returned, just an empty array!
[/quote]

Hi there,
if you backslash the brackets, it should work. Try:
$files = glob("\[myfolder\]/*.txt");
Hope this helps.
Sam Yong - hellclanner at live [dot] com
18.07.2007 14:31
An alternative to this glob function. Like what edogs [at] dogsempire.com said, opendir should be faster than glob. I have not tested timing for this function but it works perfectly for me on my PHP v5.2.2 server.

<?php

$_foo
='/server/public_html/path/';

function
s_glob($dir){
$files = array();
if(
is_dir($dir)){
    if(
$dh=opendir($dir)){
    while((
$file = readdir($dh)) !== false){
       
$files[]=$dir.$file;
    }}
}
return
$files;
}

print_r(s_glob($_foo));

?>

This function returns an empty array if no files are found in the directory or the path specified is not a directory.
hofmann dot niklas at web dot de
3.07.2007 23:11
if your script runs in a directory which contains brackets "[" and "]" glob does not work. example:

script path: c:/dir1/[baddir]/dir2/script.php

íf you use glob("c:/*") or similar calls in this script, it will fail!!

you do not even have to use the brackets in the first parameter of glob!
martinlarsen at bigfoot dot com
14.06.2007 14:13
glob() does not work if the path contains brackets "[" and "]".

For example, this will make it fail:

$files = glob("[myfolder]/*.txt");

No error is returned, just an empty array!
DangerousDave86
25.05.2007 19:38
I think redcube at gmx dot de's comment @ http://uk3.php.net/manual/en/function.glob.php#68869 should be added to the manual entry for this function, very useful information when trying to get every single file in a directory.
nataxia at gmail dot com
8.05.2007 1:05
Something I used to sort dir & subdir into array (multidimensional) reflecting dir structure.

    function getRecursiveFolderList($curDir,$currentA=false)
      {                   
        $dirs = glob($curDir . '/*', GLOB_ONLYDIR);    
       
        $cur = 0;
        foreach($dirs as $dir)
          {
            $currentA[$cur]['path'] = $dir;
            $currentA[$cur] = $this->getRecursiveFolderList($dir,$currentA[$cur]);
               
            ++$cur;
          }

        return $currentA;
      }

25.03.2007 18:41
Reply to ny_obaATgmxDOTnet:

You could also use sql_regcase() to build a pattern for case insensitive matches.
You may also want to set the locale before, so it is used when building the pattern.

<?php

$pattern
= sql_case("*.pdf");

var_dump(glob($pattern));

?>

should therefore match file.pdf AND OtherFile.PDF

See http://www.php.net/sql_regcase for more information.
alan at ridersite dot org
18.03.2007 20:26
A couple of notes:
glob() handles symbolic filesystem links and resolves references to './', '../'  nicely and handles an extra '/' character , at least on X-systems. e.g., glob("../*") will do next higher dir.

This is good to use so warnings or errors show as "../foo" and not your system's full path. 

Several of the examples use a notation "*.*" when just plain "*" does the same thing.  The "*.*" notation is misleading as it implies foo.ext will not be found with "*" because the "." is not present.

Watch the flags must not be strings. They are defined constants. Thus,
glob("../*", GLOB_ONLYDIR)  works;
glob("../*", "GLOB_ONLYDIR")  does not.
viajy at yoyo dot org
10.02.2007 13:50
this is a recursive function i wrote to return an array of all subdirectories of a dir

function listdirs($dir) {
    static $alldirs = array();
    $dirs = glob($dir . '/*', GLOB_ONLYDIR);
    if (count($dirs) > 0) {
        foreach ($dirs as $d) $alldirs[] = $d;
    }
    foreach ($dirs as $dir) listdirs($dir);
    return $alldirs;
}

example:
print_r(listdirs('/some/path'));
lesion at autistici dot org
4.12.2006 17:14
Maybe all of you still know this, but it seems that if the directory contains some unresolved symlink, glob() simply ignore those files.
torch at torchsdomain dot com
22.11.2006 21:25
Here is simple function that will find and remove all files (except "." ones) that match the expression ($match, "*" as wildcard) under starting directory ($path) and all other directories under it.

function rfr($path,$match){
   static $deld = 0, $dsize = 0;
   $dirs = glob($path."*");
   $files = glob($path.$match);
   foreach($files as $file){
      if(is_file($file)){
         $dsize += filesize($file);
         unlink($file);
         $deld++;
      }
   }
   foreach($dirs as $dir){
      if(is_dir($dir)){
         $dir = basename($dir) . "/";
         rfr($path.$dir,$match);
      }
   }
   return "$deld files deleted with a total size of $dsize bytes";
}
BigueNique at yahoo dot ca
11.11.2006 4:57
<?
//safe_glob() by BigueNique at yahoo dot ca
//Function glob() is prohibited on some servers for security reasons as stated on:
//http://seclists.org/fulldisclosure/2005/Sep/0001.html
//(Message "Warning: glob() has been disabled for security reasons in (script) on line (line)")
//safe_glob() intends to replace glob() for simple applications
//using readdir() & fnmatch() instead.
//Since fnmatch() is not available on Windows or other non-POSFIX, I rely
//on soywiz at php dot net fnmatch clone.
//On the final hand, safe_glob() supports basic wildcards on one directory.
//Supported flags: GLOB_MARK. GLOB_NOSORT, GLOB_ONLYDIR
//Return false if path doesn't exist, and an empty array is no file matches the pattern
function safe_glob($pattern, $flags=0) {
   
$split=explode('/',$pattern);
   
$match=array_pop($split);
   
$path=implode('/',$split);
    if ((
$dir=opendir($path))!==false) {
       
$glob=array();
        while((
$file=readdir($dir))!==false) {
            if (
fnmatch($match,$file)) {
                if ((
is_dir("$path/$file"))||(!($flags&GLOB_ONLYDIR))) {
                    if (
$flags&GLOB_MARK) $file.='/';
                   
$glob[]=$file;
                }
            }
        }
       
closedir($dir);
        if (!(
$flags&GLOB_NOSORT)) sort($glob);
        return
$glob;
    } else {
        return
false;
    }   
}

//thanks to soywiz for the following function, posted on http://php.net/fnmatch
//soywiz at php dot net
//17-Jul-2006 10:12
//A better "fnmatch" alternative for windows that converts a fnmatch pattern into a preg one. It should work on PHP >= 4.0.0
if (!function_exists('fnmatch')) {
    function
fnmatch($pattern, $string) {
        return @
preg_match('/^' . strtr(addcslashes($pattern, '\\.+^$(){}=!<>|'), array('*' => '.*', '?' => '.?')) . '$/i', $string);
    }
}
?>
guilleva at gmail dot com
20.10.2006 5:54
In some systems (AIX for example) GLOB_BRACE isn't defined and you get the error:
glob() expects parameter 2 to be long, string given in /XX/XX.php

<?

foreach (glob("{*.pdf,*.PDF}",GLOB_BRACE ) as $filename) {
      echo
"$filename \n";
}

?>

The method may help you in this case.

<?

foreach (array_merge(glob("*.pdf"),glob("*.PDF")) as $filename) {
      echo
"$filename \n";
}

?>
joseph dot morphy at gmail dot com
16.08.2006 20:01
<?php
$html_array
= glob("*.html");

function
sort_by_mtime($file1,$file2) {
   
$time1 = filemtime($file1);
   
$time2 = filemtime($file2);
    if (
$time1 == $time2) {
        return
0;
    }
    return (
$time1 < $time2) ? 1 : -1;
    }

usort($html_array,"sort_by_mtime");
//$html_array is now ordered by the time it was last modified
?>
redcube at gmx dot de
14.08.2006 11:22
The answer for the difference in the dirsize function of "management at twilightus dot net":

glob('*') ignores all 'hidden' files by default. This means it does not return files that start with a dot (e.g. ".file").
If you want to match those files too, you can use "{,.}*" as the pattern with the GLOB_BRACE flag.

<?php
// Search for all files that match .* or *
$files = glob('{,.}*', GLOB_BRACE);
?>

Note: This also returns the directory special entries . and ..
management at twilightus dot net
10.08.2006 21:40
I was making a directory filesize function but found there's a slight difference between glob and readdir in terms of getting sizes.

<?php
function dirsize_glob($dir)
{
   
$size = 0;
   
$dir .= (!ereg('/$', $dir)) ? '/' : '';

    foreach (
glob($dir . '*') as $file)
    {
       
$size += (is_dir($file)) ? dirsize_glob($file) : filesize($file);
    }

    return
$size;
}

function
dirsize_readdir($dir)
{
   
$size = 0;
   
$dir .= (!ereg('/$', $dir)) ? '/' : '';

   
$handle = opendir($dir);
    while ((
$file = readdir($handle)) !== FALSE)
    {
        if (!
ereg('^\.{1,2}$', $file))
        {
           
$size += (is_dir($dir . $file)) ? dirsize_readdir($dir . $file) : filesize($dir . $file);
        }
    }
   
closedir($handle);

    return
$size;
}
?>

For a directory that's 529216 bytes, readdir correctly gives 529216 while glob gives 528996, a difference of 220 bytes. Anyone know why there's such a difference?
okumurya at hotmail dot com
19.07.2006 11:25
4.3.8 and 4.4.2 has incompatible behavior.
If there is no glob result, 4.4.2 return empty array but 4.3.8 returns FALSE.

code:
<?php
$a
= glob('hoge');
var_dump($a);
?>

result at 4.3.8:
 bool(false)

result at 4.4.2:
 array(0) {
 }
c_windows_temp at hotmail dot com
7.06.2006 1:53
Note that this function does not list broken symbolic links.
ny_obaATgmxDOTnet
3.04.2006 17:51
Case insensitive version of this function for mswin:

// only supported flags are GLOB_NOSORT | GLOB_ONLYDIR
function iglob($pattern, $flags)
{
  $path = preg_split(
      '#(?<=\A|[\\\\/])((?>[^\\\\/*?]*)[*?](?>[^\\\\/]*))(?=\Z|[\\\\/])#',
      $pattern, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY
    );

  foreach ($path as &$n)
    if (preg_match('/[*?]/', $n))
    {
      $re = '';
      for ($i = 0, $l = strlen($n); $i < $l; $i++)
        switch($n{$i})
        {
          case '*': $re .= '.*'; break;
          case '?': $re .= '.'; break;
          default: $re .= sprintf('\x%02x', ord($n{$i}));
        }
      $n = array(0, "/^$re$/i");
    }
    else
      $n = array(1, $n);

  $res = array();
  iglob_DFS($path, $flags, '', 0, $res);
  if (!($flags & GLOB_NOSORT))
    sort($res);

  return $res;
}

function iglob_DFS($path, $flags, $parent, $lvl, &$res)
{
  $depth = count($path) - 1;

  if (($lvl < $depth) && $path[$lvl][0])
    $parent .= $path[$lvl++][1];

  $files = array();
  if ($path[$lvl][0])
    $files[] = $path[$lvl][1];
  else
    if ($d = @opendir(($parent == '') ? '.' : $parent))
    {
      while (($n = readdir($d)) !== false)
        if ($n != '.' && $n != '..')
          $files[] = $n;
      closedir($d);
    }

  foreach ($files as $f)
    if ($path[$lvl][0] || preg_match($path[$lvl][1], $f))
    {
      $fullpath = $parent.$f;
      if ($lvl == $depth)
      {
        if (!($flags & GLOB_ONLYDIR) || is_dir($fullpath))
          $res[] = $fullpath;
      }
      else
        iglob_DFS($path, $flags, $fullpath, $lvl + 1, $res);
    }
}
edogs [at] dogsempire.com
4.03.2006 2:34
funny enough, but our testing opendir VS glob

show advantage of opendir by speed

0.00115704536438
and
0.0068039894104

or if to pass 200 times
0.210277080536
vs
1.2976038456
info at urbits dot com
6.01.2006 13:26
I have been working towards a CMS-type design that is both modular and quite flat. For example, included files are all one level below the installation folder.

glob() just help me get rid of a lot of opendir() hassle. I wasn't sure if the double asterix would work - but it's fine:

foreach (glob(SERVER_PATH."/*/includes/*.php") as $inc) {
   require($inc);
}
admiral [at] nuclearpixel [dot] com
23.11.2005 17:38
I've written a function that I've been using quite a lot over the past year or so. I've built whole websites and their file based CMSs based on this one function, mostly because (I think) databases are not as portable as groups of files and folders. In previous versions, I used opendir and readdir to get contents, but now I can do in one line what used to take several. How? Most of the work in the whole script is done by calling

glob("$dir/*")

Giving me an array containing the names of the items in the folder, minus the ones beginning with '.', as well as the ones I specify.

<?php

/* alpharead version 3: This function returns an array containing the names of the files inside any given folder, excluding files that start with a '.', as well as the filenames listed in the '$killit' array. This array is sorted using the 'natural alphabetical' sorting manner. If no input is given to the function, it lists items in the script's interpreted folder. Version 3 fixes a MAJOR bug in version 2 which corrupted certain arrays with greater than 5 keys and one of the supposedly removed filenames.
written by Admiral at NuclearPixel.com */

function alpharead3($dir){
if(!
$dir){$dir = '.';}
foreach(
glob("$dir/*") as $item){$sort[]= end(explode('/',$item));}

$killit = array('index.html', 'index.php', 'thumbs.db', 'styles.css');
$killcounter = 0;
foreach(
$sort as $sorteditem){
foreach(
$killit as $killcheck){
if(
strtolower($sorteditem) == strtolower($killcheck))
{unset(
$sort[$killcounter]);}
}
$killcounter++;}
if(
$sort){natsort($sort);}
foreach(
$sort as $item){$return[]= $item;}

if(!
$return){return array();}
return
$return;
}

//some basic usage

$folder = 'images';
foreach(
alpharead3($folder) as $item)
{
echo
'<img src="'.$folder.'/'.$item.'"><br>'.$item."\n";
}

?>

Commens on this function are welcome!
Jacob Eisenberg
6.10.2005 7:55
Note that on Windows, glob distinguishes between uppercase and lowercase extensions, so if the directory contains a file "test.txt" and you glob for "*.TXT" then the file will not be found!
That bug only happens when you use patterns containing "*", like the example above. If you for example search for the full filename "test.TXT" then everything works correctly.
DMan
28.08.2005 9:59
Whilst on Windows, a path starting with a slash resolves OK for most file functions - but NOT glob.
If the server is LAUNCHED (or chdir()ed) to W:, then
file_exists("/temp/test.txt")
returns true for the file "W:/temp/test.txt".
But glob("/temp/*.txt") FAILS to find it!

A solution (if you want to avoid getting drive letters into your code) is to chdir() first, then just look for the file.
<?php
$glob
="/temp/*.txt";
chdir(dirname($glob));
// getcwd() is now actually "W:\temp" or whatever

foreach (glob(basename($glob)) as $filename) {
  
$filepath = dirname($glob)."/".$filename; // must re-attach full path
  
echo "$filepath size " . filesize($filepath) . "\n";
}
?>

Note also, glob() IS case sensitive although most other file funcs on Windows are not.
x_terminat_or_3 at yahoo dot country:fr
7.07.2005 0:36
This is a replacement for glob on servers that are running a php version < 4.3

It supports * and ? jokers, and stacking of parameters with ; 

So you can do

<? $results=glob('/home/user/*.txt;*.doc') ?>

And it will return an array of matched files. 

As is the behaviour of the built-in glob function, this one will also return boolean false if no matches are found, and will use the current working directory if none is specified.

<?php
if(!(function_exists('glob')))
{function
glob($pattern)
 {
#get pathname (everything up until the last / or \)
 
$path=$output=null;
  if(
PHP_OS=='WIN32')
  
$slash='\\';
  else
  
$slash='/';
 
$lastpos=strrpos($pattern,$slash);
  if(!(
$lastpos===false))
  {
$path=substr($pattern,0,-$lastpos-1); #negative length means take from the right
  
$pattern=substr($pattern,$lastpos);
  }
  else
  {
#no dir info, use current dir
  
$path=getcwd();
  }
 
$handle=@ opendir($path);
  if(
$handle===false)
   return
false;
  while(
$dir=readdir($handle))
  {if(
pattern_match($pattern,$dir))
   
$output[]=$dir;
  }
 
closedir($handle);
  if(
is_array($output))
   return
$output;
  return
false;
 }

 function
pattern_match($pattern,$string)
 {
#basically prepare a regular expression
 
$out=null;
 
$chunks=explode(';',$pattern);
  foreach(
$chunks as $pattern)
  {
$escape=array('$','^','.','{','}',
                
'(',')','[',']','|');
   while(
strpos($pattern,'**')!==false)
   
$pattern=str_replace('**','*',$pattern);
   foreach(
$escape as $probe)
   
$pattern=str_replace($probe,"\\$probe",$pattern);
  
$pattern=str_replace('?*','*',
            
str_replace('*?','*',
             
str_replace('*',".*",
              
str_replace('?','.{1,1}',$pattern))));
  
$out[]=$pattern;
  }
  if(
count($out)==1)
   return(
eregi("^$out[0]$",$string));
  else
   foreach(
$out as $tester)
    if(
eregi("^$tester$",$string))
     return
true;
   return
false;
 }
}
?>

This function is case insensitive, but if needed, you can do this to make it behave depending on os:

* replace eregi in the example with my_regexp

add this function
<?php
function my_regexp($pattern,$probe)
{
$sensitive=(PHP_OS!='WIN32');
 
$sensitive=false;
 return (
$sensitive?
    
ereg($pattern,$probe):
    
eregi($pattern,$probe));
}
?>
mjs15451 at hotmail dot com
18.06.2005 0:03
In regards to the comments made by: NOSPAM sketch at infinite dot net dot au, he is wrong about Unix/Linux (I can't speak for Windows).  I am running PHP 5.0.4 and I ran a bunch of different tests on relative and absolute paths using the glob function and they all work on Unix/Linux.  I also tested glob on empty directories and patterns which don't match any files (even directories or files which don't exist) and it __always__ returns an empty array.  I couldn't get the glob function to return false so it looks like it always returns an array.
Michael T. McGrew
17.05.2005 4:12
Take all file names in the directory and put them in a link.
<?php
foreach (glob("*.*") as $filename)
{
   echo
"<a href=\"".$filename."\">".$filename."</a><br/>";
}
?>
cgamedude at yahoo dot com
5.05.2005 12:38
Here is the *correct* way to do a reverse-alphabetical search:
<?
$Results
= glob( 'blah.*' );
rsort( $Results );
?>
There now, wasn't that easy? :)
Deviant
5.04.2005 1:53
A slight edit on the globr() function stated by sthomas. This does exactly the same just works on windows systems for < PHP 4.3.3. :

<?php

function globr($sDir, $sPattern, $nFlags = NULL) {
   
$aFiles = glob("$sDir/$sPattern", $nFlags);
   
$files = getDir($sDir);
    if (
is_array($files)) {
        foreach(
$files as $file ) {
           
$aSubFiles = globr($file, $sPattern, $nFlags);
           
$aFiles = array_merge($aFiles,$aSubFiles);
        }
    }
    return
$aFiles;
}

function
getDir($sDir) {
   
$i=0;
    if(
is_dir($sDir)) {
        if(
$rContents = opendir($sDir)) {
            while(
$sNode = readdir($rContents)) {
                if(
is_dir($sDir.'/'.$sNode )) {
                    if(
$sNode !="." && $sNode !="..") {
                       
$aDirs[$i] = $sDir.'/'.$sNode ;
                       
$i++;
                    }
                }
            }
        }
    }
    return
$aDirs;
}

?>
cjcommunications at gmail dot com
1.04.2005 15:02
Here is a way I used glob() to browse a directory, pull the file name out, resort according to the most recent date and format it using date(). I called the function inside a <select> and had it go directly to the PDF file:

function browsepdf(){
    $pdffile=glob("printable/*.pdf");
    rsort($pdffile);
    foreach($pdffile as $filename){
        $filename=ltrim($filename, "printable/");
        $filename=rtrim($filename, ".pdf");
        $file=$filename;
        $datetime=strtotime($filename);
        $newdate=strtotime("+3 days",$datetime);
        $filenamedate=date("F d", $datetime);
        $filenamedate.=" - ".date("F d, Y", $newdate);
        echo "<option value='$file'>$filenamedate</option>";
    }
}
fraggy(AT)chello.nl
24.03.2005 0:23
glob caused me some real pain in the buttom on windows, because of the DOS thing with paths (backslashes instead of slashes)...

This was my own fault because I "forgot" that the backslash, when used in strings, needs to be escaped, but well, it can cause a lot of confusion, even for people who are not exactly newbies anymore...

For some reason, I didn't have this problem with other file operations (chdir, opendir, etc...), which was the most confusing of all...

So, for people running scripts on Windows machines (Dos95, 98 or WinNT or DosXP), just remember this:

glob('c:\temp\*.*'); // works correctly, returns an array with files.
glob("c:\temp\*.*"); // does NOT work... the backslashes need to be escaped...
glob("c:\\temp\\*.*"); // that works again...

This is especially confusing when temporary writable directories are returned as an unescaped string.

$tempdir = getenv('TEMP');
// this returns "C:\DOCUME~1\user\LOCALS~1\Temp"
so in order to scan that directoy I need to do:

glob($tempdir . "\\*.*");

Or perhaps it's easier to replace all backslashes with slashes in order to avoid these kinds of confusions...

glob("c:/temp/*.*"); // works fine too...

I know I'm not contributing anything new here, but I just hope this post may avoid some unnecessary headaches...
NOSPAM sketch at infinite dot net dot au
15.03.2005 2:05
in the example below, i found i got an error if the directory was empty.

<?php
foreach (glob("*.txt") as $filename) {
   echo
"$filename size " . filesize($filename) . "\n";
}
?>

I think its because glob()'ing an empty directory returns false, and so calling foreach (false as $value) will obviously break.

to fix this, i did the following:
<?php
$files
= glob("*.txt) or array(); // give it an empty array if the directory is empty or glob fails otherwise
   echo "
$filename size " . filesize($filename) . "\n";
}
?>

Hope this helps someone

29.01.2005 23:09
Be aware...

On Windows you need to add "/" mark:
<?php
$files
= glob("/dir/*.txt"); // Works properly.
$files = glob("dir/*.txt"); // Failure!, first letter is missing on every filename!
?>

On Unix you cant add the "/" mark:
<?php
$files
= glob("dir/*.txt"); // Works properly.
$files = glob("/dir/*.txt"); // No files found!
?>

Hope this will save your time :)

23.01.2005 22:54
The example on this page will generate a warning if the glob function does not find any filenames that match the pattern.

The glob function result will only be an array if it finds some files and the foreach statement requires its argument to be an array.

By checking for the possibility that the result of the glob function may not be an array you can eliminate the warning.

Here's a better example:

<?php
$matches
= glob("*.txt");
if (
is_array ( $matches ) ) {
   foreach (
$matches as $filename) {
      echo
"$filename size " . filesize($filename) . "\n";
   }
}
?>
Paul Gregg / Qube #efnet
31.03.2004 3:52
Just threw this together in response to a common question in irc:

Available at: http://www.pgregg.com/projects/
http://www.pgregg.com/projects/php/code/preg_find.phps

preg_find() - A function to search in a directory for files or directories matching a preg_ pattern.  Tell it the pattern, the start directory and some optional flags and it will return an array of files and their associated stat() details.  If you just want the filenames, just do an array_keys() on the result.

e.g. $files = preg_find("/\.php$/", '.', PREG_FIND_RECURSIVE);
will find all files ending in .php in the current directory and below.

Options are:
// PREG_FIND_RECURSIVE  - go into subdirectorys looking for more files
// PREG_FIND_DIRMATCH   - return directorys that match the pattern also
// PREG_FIND_FULLPATH   - search for the pattern in the full path (dir+file)
// PREG_FIND_NEGATE     - return files that don't match the pattern
// to use more than one simple seperate them with a | character

Hope you find it useful.

Paul.
Per Lundberg
25.11.2003 16:57
Be aware that on UNIX, * as the pattern will *not* match dot-files and dot-directories.  Knowing this will save you some headache.  :-)  May He bless you.
MichaelSoft
6.11.2003 12:28
Note that, in some configurations, the search is case-sensitive! You'll need to have something like:

<?php
$images
= glob("/path/to/images/{*.jpg,*.JPG}", GLOB_BRACE);
?>

Also on some servers, I have seen such scripts 'crash' with an CGI Error ("...not returning a complete set of HTTP headers...") when glob could not find any match!
ryan at wonko dot com
30.10.2003 8:03
Here's an example of how to use the GLOB_BRACE flag:

<?php
$images
= glob("/path/to/images/{*.gif,*.jpg,*.png}", GLOB_BRACE);
?>

It's also worth noting that when using the GLOB_BRACE flag in any version of PHP prior to 4.3.4, PHP will crash if no matches are found.
sthomas at townnews dot com
12.03.2003 0:41
<?php
/**
 * 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 = rglob($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;
}

?>
martin dot rode at zeroscale dot com
19.02.2003 20:37
If you don't have PHP >= 4.3 available and don't want to hassle with PHP (:-) do something like this on GNU/Linux:

<?php
foreach (explode("\n",`find -type d -maxdepth 1 ! -name ".*" -printf "%f\n" `) as $dirname) {
    print
$dirname;
}
?>

With the "find" you can "glob" whatever you like.
tmm at aon dot at
22.12.2002 1:50
I have written my own function for searching files, but it only supports ? and *
However it should be easily expandable.

<?php
// e.g. $matches=GetMachingFiles(GetContents("."),"*.txt");
function GetMatchingFiles($files, $search) {

   
// Split to name and filetype
   
if(strpos($search,".")) {
     
$baseexp=substr($search,0,strpos($search,"."));
     
$typeexp=substr($search,strpos($search,".")+1,strlen($search));
    } else {
     
$baseexp=$search;
     
$typeexp="";
    }
    
   
// Escape all regexp Characters
   
$baseexp=preg_quote($baseexp);
   
$typeexp=preg_quote($typeexp);
    
   
// Allow ? and *
   
$baseexp=str_replace(array("\*","\?"), array(".*","."), $baseexp);
   
$typeexp=str_replace(array("\*","\?"), array(".*","."), $typeexp);
       
   
// Search for Matches
   
$i=0;
    foreach(
$files as $file) {
     
$filename=basename($file);
       
      if(
strpos($filename,".")) {
       
$base=substr($filename,0,strpos($filename,"."));
       
$type=substr($filename,strpos($filename,".")+1,strlen($filename));
      } else {
       
$base=$filename;
       
$type="";
      }

      if(
preg_match("/^".$baseexp."$/i",$base) && preg_match("/^".$typeexp."$/i",$type))  {
       
$matches[$i]=$file;
       
$i++;
      }
    }
    return
$matches;
}

And if
someone's searching for a function which gets all files from a directory including the subdirectories:

// Returns all Files contained in given dir, including subdirs
function GetContents($dir,$files=array()) {
  if(!($res=opendir($dir))) exit("$dir doesn'
t exist!");
  while((
$file=readdir($res))==TRUE)
    if(
$file!="." && $file!="..")
      if(is_dir("
$dir/$file")) $files=GetContents("$dir/$file",$files);
        else array_push(
$files,"$dir/$file");
     
  closedir(
$res);
  return
$files;
}

?>
leon at leonatkinson dot com
18.10.2002 3:03
Since this function is a wrapper for the OS function of the same name, you may find it helpful to look at the man page while the exact PHP implementation is sorted out.

You might have some luck passing in the literal values of the constants defined in /usr/include/glob.h.  For example, GLOB_NOSORT is defined as (1 << 2), which is 4.  In PHP, glob('*.php', 4) will returns an unsorted list for me in RH 7.x.  YMMV.
opessin at ifrance dot com
7.07.2002 12:48
If this function is not available in your version of PHP, think looking at the 'Directory Functions' which can be used instead.
http://www.php.net/manual/en/ref.dir.php



PHP Powered Diese Seite bei php.net
The PHP manual text and comments are covered by the Creative Commons Attribution 3.0 License © the PHP Documentation Group - Impressum - mail("TO:Reinhard Neidl",...)