* Version 1.0: 20 March 2004, Updated 20 April 2004 * Version 2.1: Updated 18 April 2007 to add the ability to sort the result set * Version 2.2: Updated 9 June 2007 to prevent multiple calls to sort during recursion * Version 2.3: Updated 12 June 2009 to allow for sorting by extension and prevent following * symlinks by default * Version 2.4: Updated 17 May 2020 PHP7.2 deprecates create_function, updated to a Closure function. * Thanks to Chris Johnson for emailing me to ask for this update. * * Version: 2.4 * This function is backwards capatible with any code written for a * previous version of preg_find() * * Open Source Code: If you use this code on your site for public * access (i.e. on the Internet) then you must attribute the author and * source web site: http://www.pgregg.com/projects/php/preg_find/preg_find.phps * Working examples: http://www.pgregg.com/projects/php/preg_find/ * */ define('PREG_FIND_RECURSIVE', 1); define('PREG_FIND_DIRMATCH', 2); define('PREG_FIND_FULLPATH', 4); define('PREG_FIND_NEGATE', 8); define('PREG_FIND_DIRONLY', 16); define('PREG_FIND_RETURNASSOC', 32); define('PREG_FIND_SORTDESC', 64); define('PREG_FIND_SORTKEYS', 128); define('PREG_FIND_SORTBASENAME', 256); # requires PREG_FIND_RETURNASSOC define('PREG_FIND_SORTMODIFIED', 512); # requires PREG_FIND_RETURNASSOC define('PREG_FIND_SORTFILESIZE', 1024); # requires PREG_FIND_RETURNASSOC define('PREG_FIND_SORTDISKUSAGE', 2048); # requires PREG_FIND_RETURNASSOC define('PREG_FIND_SORTEXTENSION', 4096); # requires PREG_FIND_RETURNASSOC define('PREG_FIND_FOLLOWSYMLINKS', 8192); // PREG_FIND_RECURSIVE - go into subdirectorys looking for more files // PREG_FIND_DIRMATCH - return directorys that match the pattern also // PREG_FIND_DIRONLY - return only directorys that match the pattern (no files) // PREG_FIND_FULLPATH - search for the pattern in the full path (dir+file) // PREG_FIND_NEGATE - return files that don't match the pattern // PREG_FIND_RETURNASSOC - Instead of just returning a plain array of matches, // return an associative array with file stats // PREG_FIND_FOLLOWSYMLINKS - Recursive searches (from v2.3) will no longer // traverse symlinks to directories, unless you // specify this flag. This is to prevent nasty // endless loops. // // You can also request to have the results sorted based on various criteria // By default if any sorting is done, it will be sorted in ascending order. // You can reverse this via use of: // PREG_FIND_SORTDESC - Reverse order of sort // PREG_FILE_SORTKEYS - Sort on the keyvalues or non-assoc array results // The following sorts *require* PREG_FIND_RETURNASSOC to be used as they are // sorting on values stored in the constructed associative array // PREG_FIND_SORTBASENAME - Sort the results in alphabetical order on filename // PREG_FIND_SORTMODIFIED - Sort the results in last modified timestamp order // PREG_FIND_SORTFILESIZE - Sort the results based on filesize // PREG_FILE_SORTDISKUSAGE - Sort based on the amount of disk space taken // PREG_FIND_SORTEXTENSION - Sort based on the filename extension // to use more than one simply seperate them with a | character // Search for files matching $pattern in $start_dir. // if args contains PREG_FIND_RECURSIVE then do a recursive search // return value is an associative array, the key of which is the path/file // and the value is the stat of the file. Function preg_find($pattern, $start_dir='.', $args=NULL) { static $depth = -1; ++$depth; $files_matched = array(); $fh = opendir($start_dir); if (!$fh) { return null; } while (($file = readdir($fh)) !== false) { if (strcmp($file, '.')==0 || strcmp($file, '..')==0) continue; $filepath = $start_dir . '/' . $file; if (preg_match($pattern, ($args & PREG_FIND_FULLPATH) ? $filepath : $file)) { $doadd = is_file($filepath) || (is_dir($filepath) && ($args & PREG_FIND_DIRMATCH)) || (is_dir($filepath) && ($args & PREG_FIND_DIRONLY)); if ($args & PREG_FIND_DIRONLY && $doadd && !is_dir($filepath)) $doadd = false; if ($args & PREG_FIND_NEGATE) $doadd = !$doadd; if ($doadd) { if ($args & PREG_FIND_RETURNASSOC) { // return more than just the filenames $fileres = array(); if (function_exists('stat')) { $fileres['stat'] = stat($filepath); $fileres['du'] = $fileres['stat']['blocks'] * 512; } if (function_exists('fileowner')) $fileres['uid'] = fileowner($filepath); if (function_exists('filegroup')) $fileres['gid'] = filegroup($filepath); if (function_exists('filetype')) $fileres['filetype'] = filetype($filepath); if (function_exists('mime_content_type')) $fileres['mimetype'] = mime_content_type($filepath); if (function_exists('dirname')) $fileres['dirname'] = dirname($filepath); if (function_exists('basename')) $fileres['basename'] = basename($filepath); if (($i=strrpos($fileres['basename'], '.'))!==false) $fileres['ext'] = substr($fileres['basename'], $i+1); else $fileres['ext'] = ''; if (isset($fileres['uid']) && function_exists('posix_getpwuid')) $fileres['owner'] = posix_getpwuid ($fileres['uid']); $files_matched[$filepath] = $fileres; } else array_push($files_matched, $filepath); } } if ( is_dir($filepath) && ($args & PREG_FIND_RECURSIVE) ) { if (!is_link($filepath) || ($args & PREG_FIND_FOLLOWSYMLINKS)) $files_matched = array_merge($files_matched, preg_find($pattern, $filepath, $args)); } } closedir($fh); // Before returning check if we need to sort the results. if (($depth==0) && ($args & (PREG_FIND_SORTKEYS|PREG_FIND_SORTBASENAME|PREG_FIND_SORTMODIFIED|PREG_FIND_SORTFILESIZE|PREG_FIND_SORTDISKUSAGE)) ) { $order = ($args & PREG_FIND_SORTDESC) ? 1 : -1; $filesort = function ($a, $b) use ($order) { if ($a==$b) return 0; else return ($a<$b) ? $order : 0-$order; }; if ($args & PREG_FIND_RETURNASSOC) { if ($args & PREG_FIND_SORTMODIFIED) $filesort = function ($a, $b) use ($order) { $a1 = $a['stat']['mtime']; $b1 = $b['stat']['mtime']; if ($a1==$b1) return 0; else return ($a1<$b1) ? $order : 0-$order; }; if ($args & PREG_FIND_SORTBASENAME) $filesort = function ($a, $b) use ($order) { $a1 = $a['basename']; $b1 = $b['basename']; if ($a1==$b1) return 0; else return ($a1<$b1) ? $order : 0-$order; }; if ($args & PREG_FIND_SORTFILESIZE) $filesort = function ($a, $b) use ($order) { $a1 = $a['stat']['size']; $b1 = $b['stat']['size']; if ($a1==$b1) return 0; else return ($a1<$b1) ? $order : 0-$order; }; if ($args & PREG_FIND_SORTDISKUSAGE) $filesort = function ($a, $b) use ($order) { $a1 = $a['du']; $b1 = $b['du']; if ($a1==$b1) return 0; else return ($a1<$b1) ? $order : 0-$order; }; if ($args & PREG_FIND_SORTEXTENSION) $filesort = function ($a, $b) use ($order) { $a1 = $a['ext']; $b1 = $b['ext']; if ($a1==$b1) return 0; else return ($a1<$b1) ? $order : 0-$order; }; } uasort($files_matched, $filesort); } --$depth; return $files_matched; } ?>