文字

glob

(PHP 4 >= 4.3.0, PHP 5, PHP 7)

glob寻找与模式匹配的文件路径

说明

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

glob() 函数依照 libc glob() 函数使用的规则寻找所有与 pattern 匹配的文件路径,类似于一般 shells 所用的规则一样。不进行缩写扩展或参数替代。

参数

pattern

The pattern. No tilde expansion or parameter substitution is done.

flags

有效标记有:

  • GLOB_MARK - 在每个返回的项目中加一个斜线
  • GLOB_NOSORT - 按照文件在目录中出现的原始顺序返回(不排序)
  • GLOB_NOCHECK - 如果没有文件匹配则返回用于搜索的模式
  • GLOB_NOESCAPE - 反斜线不转义元字符
  • GLOB_BRACE - 扩充 {a,b,c} 来匹配 'a','b' 或 'c'
  • GLOB_ONLYDIR - 仅返回与模式匹配的目录项
  • GLOB_ERR - 停止并读取错误信息(比如说不可读的目录),默认的情况下忽略所有错误

返回值

返回一个包含有匹配文件/目录的数组。如果出错返回 FALSE

Note:

On some systems it is impossible to distinguish between empty match and an error.

更新日志

版本 说明
5.1.0 GLOB_ERR was added
4.3.3 GLOB_ONLYDIR 在 Windows 或者其它不使用 GNU C 库的系统上开始可用。

范例

Example #1 怎样用 glob() 方便地替代 opendir() 和相关函数

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

以上例程的输出类似于:

funclist.txt size 44686
funcsummary.txt size 267625
quickref.txt size 137820

注释

Note: 此函数不能作用于远程文件,被检查的文件必须是可通过服务器的文件系统访问的。

Note: 此函数在一些系统上还不能工作(例如一些旧的 Sun OS)。

Note: GLOB_BRACE 在一些非 GNU 系统上无效,比如 Solaris。

参见

  • opendir() - 打开目录句柄
  • readdir() - 从目录句柄中读取条目
  • closedir() - 关闭目录句柄
  • fnmatch() - 用模式匹配文件名

用户评论:

[#1] sharshun dot aliaksandr at gmail dot com [2015-11-04 02:26:11]

<?php

function glob_recursive($pattern$flags 0){
// forked from https://github.com/rodurma/PHP-Functions/
    // blob/master/glob_recursive.php
  
$files glob($pattern$flags);
       
  foreach (
glob(dirname($pattern).'**");
    
$arr=array_unique(array_merge($a$ar));

    foreach (
$arr as $v) {
        if (
is_dir($v)) {
            
$arra[0][]=$v.'/';
        } else {
            
$arra[1][]=$v;
        }
    }
    
sort($arra);
    return 
$arra;
}
$a=dirInfoReGet('c:/test_directory/');
print_r($a);

?>


http://i.stack.imgur.com/H7UF3.jpg

Best regards.

[#2] Anxiety35 at gmail dot com [2014-12-01 21:20:19]

After fiddling with GLOB_BRACE a bunch, I have found the most items that can be included in the braces is about 10 before glob no longer returns any matches.

I have a scenario where there can be a thousand or more files to check for where I can't pattern match and need to check specific names. I was hoping to batch them in large groups to see if it would help performance. However, if I include more than 10 in a GLOB_BRACE the function will return FALSE.

[#3] rene dot rathmann at gmx dot de [2014-01-02 11:05:04]

You can do a recursive file search with yield.

<?php
function findAllDirs($start) {
    
$dirStack=[$start];
    while(
$dir=array_shift($dirStack)) {
        
$ar=glob($dir.'
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;
    
}
?>

[#18] ottodenn at gmail dot com [2010-02-01 02:18:58]

just a quick one:

get all dirs, without files:
<?php
$dirs 
array_filter(glob($path.'*'), 'is_dir');
?>

[#19] dragos dot rusu at ymail dot com [2009-11-11 00:52:58]

Glob function doesn't return the hidden files (including ".*" files). PHP5 RecursiveIterator can be used for iterating through directories recursively.

[#20] wang yun [2009-09-22 06:00:51]

A function to quickly remove a directory (works in seconds for a hundred thousand files)

<?php

function rmrf($dir) {
    foreach (
glob($dir) as $file) {
        if (
is_dir($file)) { 
            
rmrf("$file*dirincludes

function alpharead3($dir){
if(!
$dir){$dir '.';}
foreach(
glob("$dir
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
$file = new FileHandler($_FILES['excel_file']);
$inputFileName = $file->uploadFile()->fileNameSanitized();  // File to read
                ...

}
catch(Exception $e)
{
die('Error cargando archivo "'.($file->fileNameOriginal()).'": '.$e->getMessage());
}


}
?>

[#3] uramihsayibok, gmail, com [2007-08-12 21:18:12]

It isn't mentioned anywhere that I've seen, but $filename *is* case-sensitive on Windows.
It means that while C:\Windows\TEMP\php123.tmp may have been uploaded, C:\Windows\Temp\php123.tmp was not.

I found this out because I was using realpath() on the filename which 'fixed' the case (my Temp folder is in titlecase, not uppercase - thank you Vista).

Anyways, the problem was that PHP used %TEMP% to determine the destination for the uploaded file, and %TEMP% used the all-capitals version of the path. Changing it to use titlecase instead + restarting Apache fixed the problem.

[#4] YLearn [2005-10-10 10:42:34]

Just looked at what I posted again and found several mistakes of the major and minor sort.  That's what I get for posting before I finish my coffee.  This should work better (i.e. should work in the first place):

<?php
   
default: //a default error, just in case!  :)
       
echo "There was a problem with your upload.";
       
$err_msg "Unrecognized file POST error: ".$HTTP_POST_FILES['userfile']['error'];
       if (!(
strpos($err_msg"\n") === false)) {
           
$err_lines explode("\n"$err_msg);
           foreach (
$err_lines as $msg) {
               
error_log($msg0);
           }
       } else {
           
error_log($err_msg0);
       }
       break;
?>

[#5] YLearn [2005-10-10 09:41:15]

Regarding topcat's suggested change, I am split on doing that.  I don't like showing users errors that may give them more information than they should have (or show that I haven't provided for that particular error).  But I want to know when there are errors that fall to the default case so I can fix my code.  What I will typically do is write them to the error log something like this modification to metaltoad's post (takes into account the possibility of multi-line errors which error_log doesn't handle well):

<?php
    
default: //a default error, just in case!  :)
        
echo "There was a problem with your upload.";
        
$err_msg "Unrecognized file POST error: ".$HTTP_POST_FILES['userfile']['error'];
        if ((
strpos($err_msg"\n") === 0) {
            
$err_lines explode("\n"$err_msg);
            foreach (
$err_lines as $msg) {
                
error_log($msg0);
            }
        } else {
            
error_log($err_msg0)
        }
        break;
?>

[#6] juk [2005-09-18 15:26:51]

If your $_FILES and $_POST are empty, this can be due to
- the limit set by post_max_size in php.ini
- the limit set by upload_max_filesize in php.ini

Unfortunately the first limit is not reported back as an error code in $_FILES['error'].

[#7] topcat [2005-07-14 04:56:37]

Just a little tip to info at metaltoad's comment:
It's good practice to print error code when it can't be recognized:

   default: //print the error code
     echo "Unrecognized error code: ".$HTTP_POST_FILES['userfile']['error'];
     break;

[#8] [2005-04-23 12:29:03]

make use u got the enctype="multipart/form-data" in ur form tag otrherwise nothing works... took me two hours to find that out.......

[#9] beer UNDRSCR nomaed AT hotmail DOT com [2005-04-15 04:21:19]

Regarding the comment of info at metaltoad dot net
@ 19-Feb-2003 04:03

<?php
// ... yada yada yada...
preg_match("/.exe$|.com$|.bat$|.zip$|.doc$|.txt$/i"$HTTP_POST_FILES['userfile']['name']))
// ... yada yada yada...
?>


This will not work. It will, but not correctly.
You shuld escape the . (dot) for the preg function,
and escape the $ (dollar) sign for PHP, or use
single-quoted string...

The syntax should be (much shorter and neater):

<?php
// ... yada yada yada...
preg_match('/\\.(exe|com|bat|zip|doc|txt)$/i'$_FILES['userfile']['name']))
// ... yada yada yada...
?>

[#10] lots2learn at gmail dot com [2005-02-06 21:13:02]

if files are not getting uploaded and $_FILE array is empty ..and your code looks fine..then check php.ini file..the file_uploads option should be turned 'On' to allow file uploads. Turn it on and restart apache to have effect .

[#11] info at metaltoad dot net [2003-02-19 13:03:29]

As of PHP 4.2.0, rather than automatically assuming a failed file uploaded is a file attack, you can use the error code associated with the file upload to check and see why the upload failed.  This error code is stored in the userfile array (ex: $HTTP_POST_FILES['userfile']['error']). 

Here's an example of a switch:

if (is_uploaded_file($userfile)) {
  
  //include code to copy tmp file to final location here...
  
}else{
  switch($HTTP_POST_FILES['userfile']['error']){
    case 0: //no error; possible file attack!
      echo "There was a problem with your upload.";
      break;
    case 1: //uploaded file exceeds the upload_max_filesize directive in php.ini
      echo "The file you are trying to upload is too big.";
      break;
    case 2: //uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the html form
      echo "The file you are trying to upload is too big.";
      break;
    case 3: //uploaded file was only partially uploaded
      echo "The file you are trying upload was only partially uploaded.";
      break;
    case 4: //no file was uploaded
      echo "You must select an image for upload.";
      break;
    default: //a default error, just in case!  :)
      echo "There was a problem with your upload.";
      break;
}

Additionally, by testing the 'name' element of the file upload array, you can filter out unwanted file types (.exe, .zip, .bat, etc).  Here's an example of a filter that can be added before testing to see if the file was uploaded:

//rejects all .exe, .com, .bat, .zip, .doc and .txt files
if(preg_match("/.exe$|.com$|.bat$|.zip$|.doc$|.txt$/i", $HTTP_POST_FILES['userfile']['name'])){
  exit("You cannot upload this type of file.");
}

//if file is not rejected by the filter, continue normally
if (is_uploaded_file($userfile)) {

[#12] itadmin at itmusicweb dot co dot uk [2002-11-28 06:11:09]

The example brought out does not work as supposed to:

function is_uploaded_file($filename) {
    if (!$tmp_file = get_cfg_var('upload_tmp_dir')) {
        $tmp_file = dirname(tempnam('', ''));
    }
    $tmp_file .= '/' . basename($filename);
    
    return (ereg_replace('/+', '/', $tmp_file) == $filename);
}

It works only with files under ....4 or 5 kb, other files automatically get the size of 0 bytes. So something must be wrong here. Built-in is_uploaded_file() works good.

[#13] troels at NO dot SPAM dot webcode dot dk [2002-10-14 12:44:59]

to get the example to work on windows, youll have to add a line, that replaces backslashes with slashes. eg.: $filename = str_replace ("\\", "/", $filename);

also, as someone mentioned, globalizing $HTTP_POST_FILES is a good idea ...

<pre>

function is_uploaded_file($filename)
{
global $HTTP_POST_FILES;
if (!$tmp_file = get_cfg_var("upload_tmp_dir")) {
$tmp_file = dirname(tempnam("", ""));
}
$tmp_file .= "/" . basename($filename);

// fix for win platform
$filename = str_replace ("\\", "/", $filename);
return (ereg_replace("/+", "/", $tmp_file) == $filename);
}
</pre>

上一篇: 下一篇: