file_exists

(PHP 4, PHP 5, PHP 7)

file_exists检查文件或目录是否存在

说明

file_exists ( string $filename ) : bool

检查文件或目录是否存在。

参数

filename

文件或目录的路径。

在 Windows 中要用 //computername/share/filename 或者 \\computername\share\filename 来检查网络中的共享文件。

返回值

如果由 filename 指定的文件或目录存在则返回 TRUE,否则返回 FALSE

Note:

This function will return FALSE for symlinks pointing to non-existing files.

Warning

如果因为安全模式的限制而导致不能访问文件的话,该函数会返回 FALSE。然而,可以使用 include 来包含,如果文件在 safe_mode_include_dir 所指定的目录里。

Note:

The check is done using the real UID/GID instead of the effective one.

Note: 因为 PHP 的整数类型是有符号整型而且很多平台使用 32 位整型,对 2GB 以上的文件,一些文件系统函数可能返回无法预期的结果 。

范例

Example #1 测试一个文件是否存在

<?php
$filename 
'/path/to/foo.txt';

if (
file_exists($filename)) {
    echo 
"The file $filename exists";
} else {
    echo 
"The file $filename does not exist";
}
?>

错误/异常

失败时抛出E_WARNING警告。

注释

Note: 此函数的结果会被缓存。参见 clearstatcache() 以获得更多细节。

Tip

自 PHP 5.0.0 起, 此函数也用于某些 URL 包装器。请参见 支持的协议和封装协议以获得支持 stat() 系列函数功能的包装器列表。

参见

  • is_readable() - 判断给定文件名是否可读
  • is_writable() - 判断给定的文件名是否可写
  • is_file() - 判断给定文件名是否为一个正常的文件
  • file() - 把整个文件读入一个数组中

User Contributed Notes

varrg 29-Aug-2019 09:55
file_exists() is vulnerable to race conditions and clearstatcache() is not adequate to avoid it.

The following function is a good solution:

<?php
function file_exists_safe($file) {
    if (!
$fd = fopen($file, 'xb')) {
        return
true// the file already exists
   
}
   
fclose($fd);  // the file is now created, we don't need the file handler
   
return false;
}
?>

The function will create a file if non-existent, following calls will fail because the file exists (in effect being a lock).

IMPORTANT: The file will remain on the disk if it was successfully created and you must clean up after you, f.ex. remove it or overwrite it. This step is purposely omitted from the function as to let scripts do calculations all the while being sure the file won't be "seized" by another process.

NOTE: This method fails if the above function is not used for checking in all other scripts/processes as it doesn't actually lock the file.
FIX: You could flock() the file to prevent that (although all other scripts similarly must check it with flock() then, see https://www.php.net/manual/en/function.flock.php). Be sure to unlock and fclose() the file AFTER you're done with it, and not within the above function:

<?php
function create_and_lock($file) {
    if (!
$fd = fopen($file, 'xb')) {
        return
false;
    }
    if (!
flock($fd, LOCK_EX|LOCK_NB)) {  // may fail for other reasons, LOCK_NB will prevent blocking
       
fclose($fd);
       
unlink($file);  // clean up
       
return false;
    }
    return
$fd;
}

if (
$lock = create_and_lock("foo.txt")) {
   
// do stuff
   
flock($fd, LOCK_UN);  // unlock
   
fclose($fd);  // close
}
?>

SEE ALSO: https://linux.die.net/man/2/open about O_CREAT|O_EXCL (which is used with the 'x' modifier for fopen()) and problems with NFS
jag 24-May-2019 11:00
file_exists() does NOT search the php include_path for your file, so don't use it before trying to include or require.

use

    @$result = include $filename;

Yes, include does return false when the file can't be found, but it does also generate a warning. That's why you need the @. Don't try to get around the warning issue by using file_exists(). That will leave you scratching your head until you figure out or stumble across the fact that file_exists() DOESN'T SEARCH THE PHP INCLUDE_PATH.
vcoletti at tiscali dot it 26-Jul-2017 10:35
With PHP 7.0 on Ubuntu 17.04 and with the option allow_url_fopen=On, file_exists() returns always false when trying to check a remote file via HTTP.

So
        $url="http://www.somewhere.org/index.htm";
        if (file_exists($url)) echo "Wow!\n";
        else echo "missing\n";

returns always "missing", even for an existing URL.

I found that in the same situation the file() function can read the remote file, so I changed my routine in

        $url="http://www.somewhere.org/index.htm";
        if (false!==file($url)) echo "Wow!\n";
        else echo "missing\n";
               
This is clearly a bit slower, especially if the remote file is big, but it solves this little problem.
ziptwipi at goioia dot com 17-Aug-2016 05:44
Note that realpath() will return false if the file doesn't exist. So if you're going to absolutize the path and resolve symlinks anyway, you can just check the return value from realpath() instead of calling file_exists() first
broken at links dot com 14-May-2014 12:29
file_exists() will return FALSE for broken links

$ ln -s does_not_exist my_link
$ ls -l
lrwxr-xr-x   1 user  group    14 May 13 17:28 my_link -> does_not_exist
$ php -r "var_dump(file_exists('my_link'));"
bool(false)
welkom at remconijhuis dot nl 30-Dec-2013 11:10
I needed to measure performance for a project, so I did a simple test with one million file_exists() and is_file() checks. In one scenario, only seven of the files existed. In the second, all files existed. is_file() needed 3.0 for scenario one and 3.3 seconds for scenario two.  file_exists() needed 2.8 and 2.9 seconds, respectively. The absolute numbers are off course system-dependant, but it clearly indicates that file_exists() is faster.
DeyV at poczta dot php dot pl 13-Jan-2012 04:47
Great alternative to file_exists() is stream_resolve_include_path()
spark at limao dot com dot br 13-Apr-2011 07:26
this code here is in case you want to check if a file exists in another server:

<?php
function fileExists($path){
    return (@
fopen($path,"r")==true);
}
?>

unfortunately the file_exists can't reach remote servers, so I used the fopen function.
ferodano at gmail dot com 16-Sep-2009 01:54
You could use document root to be on the safer side because the function does not take relative paths:

<?php
if( file_exists( $_SERVER{'DOCUMENT_ROOT'} . "/my_images/abc.jpg"))  {
   ...
}
?>

Do not forget to put the slash '/', e.g. my doc root in Ubuntu is /var/www without the slash.
pgl at yoyo dot org 31-Jul-2009 07:03
Note that this will return false for streams, eg, php://stdin.
fabin dot gnu at gmail dot com 31-Jan-2009 01:03
The code can be used to t a filename that can be used to create a new filename.

<?php
function generateRandomString($length = 8)
{   
   
$string = "";
   
   
//character that can be used
   
$possible = "0123456789bcdfghjkmnpqrstvwxyz";
   
    for(
$i=0;$i < $length;$i++)
    {
       
$char = substr($possible, rand(0, strlen($possible)-1), 1);
       
        if (!
strstr($string, $char))
        {
           
$string .= $char;
        }
    }

    return
$string;
}

function
randomFile($folder = '', $extension = '')
{
   
$folder = trim($folder);
   
$folder = ($folder == '') ? './' : $folder;
 
   
//check if directory exist
   
if (!is_dir($folder)){ die('invalid folder given!'); }
 
   
//generate a filepath
   
$filepath = $folder . "/" . generateRandomString(128) . $extension;
   
   
//check if that filepath already exist, if it exist if generates again
    //till if gets one that doesn't exist
   
while(file_exists($filepath))
    {
       
$filepath = $folder . "/" . generateRandomString(128) . $extension;
    }
   
    return
$filepath;
}
?>
kevin at cuznersoft dot com 04-Nov-2008 08:32
My way of making sure files exist before including them is as follows (example: including a class file in an autoloader):

<?php
function __autoload($name)
{   
   
$path = explode(":", ini_get('include_path')); //get all the possible paths to the file (preloaded with the file structure of the project)
   
foreach($path as $tryThis)
    {
       
//try each possible iteration of the file name and use the first one that comes up
        // name.class.php first
       
$exists = file_exists($tryThis . '/' . $name . '.class.php');
        if (
$exists)
        {
            include_once(
$name . '.class.php');
            return;
        }
       
       
//ok that didn't work, try the other way around
       
$exists = file_exists($tryThis . '/' . 'class.' . $name . '.php');
        if (
$exists)
        {
            include_once(
'class.' . $name . '.php');
            return;
        }
       
       
//neither did that...let's try as an inc.php
       
$exists = file_exists($tryThis . '/' . $name . '.inc.php');
        if (
$exists)
        {
            include_once(
$name . '.inc.php');
            return;
        }
    }
   
   
   
// can't find it...
   
die("Class $name could not be found!");
}
?>
Avee 19-Aug-2008 08:21
I made a bit of code that sees whether a file served via RTSP is there or not:

<?php
function rtsp_exists($url) {

   
$server = parse_url($url, PHP_URL_HOST);
   
$port = "554";
   
$hdrs = "DESCRIBE " .$url ." RTSP/1.0"."\r\n\r\n";

   
//Open connection (15s timeout)
   
$sh = fsockopen($server, $port, $err, $err_otp, 15);
   
//Check connections
   
if(!$sh) return false;
   
//Send headers
   
fputs($sh,$hdrs);
   
//Receive data (1KB)
   
$rtds = fgets($sh, 1024);
   
//Close socket
   
fclose($sh);

    return
strpos($rtds, "200 OK") > 0;
}
?>
dan at sudonames dot com 05-Aug-2008 05:41
Here is a simpler version of url_exists:

<?php
function url_exists($url) {
   
$hdrs = @get_headers($url);
    return
is_array($hdrs) ? preg_match('/^HTTP\\/\\d+\\.\\d+\\s+2\\d\\d\\s+.*$/',$hdrs[0]) : false;
}
?>
stuart 26-Feb-2008 10:44
When using file_exists, seems you cannot do:

<?php
foreach ($possibles as $poss)
{
    if (
file_exists(SITE_RANGE_IMAGE_PATH .$this->range_id .'/ '.$poss .'.jpg') )
    {
       
// exists
   
}
    else
    {
       
// not found
   
}
}
?>

so you must do:

<?php
foreach ($possibles as $poss)
{
   
$img = SITE_RANGE_IMAGE_PATH .$this->range_id .'/ '.$poss .'.jpg'
   
if ( file_exists($img) )
    {
       
// exists
   
}
    else
    {
       
// not found
   
}
}
?>

Then things will work fine.

This is at least the case on this Windows system running php 5.2.5 and apache 2.2.3

Not sure if it is down to the concatenation or the fact theres a constant in there, i'm about to run away and test just that...
jaz-t at hotmail dot com 26-Feb-2008 07:12
Note on openspecies entry (excellent btw, thanks!).

If your server cannot resolve its own DNS, use the following:
$f = preg_replace('/www\.yourserver\.(net|com)/', getenv('SERVER_ADDR'), $f);

Just before the $h = @get_headers($f); line.

Replace the extensions (net|com|...) in the regexp expression as appropriate.

EXAMPLE:
File you are checking for: http://www.youserver.net/myfile.gif
Server IP: 10.0.0.125

The preg_replace will effectively 'resolve' the address for you by assigning $f as follows:
http://10.0.0.125/myfile.gif
maurice at idify dot nl 20-Nov-2007 02:45
Note: The results of this function are cached. See clearstatcache() for more details.

That's a pretty big note. Don't forget this one, since it can make your file_exists() behave unexpectedly - probably at production time ;)
marufit at gmail dot com 12-Nov-2007 03:22
Older php (v4.x) do not work with get_headers() function. So I made this one and working.

<?php
function url_exists($url) {
   
// Version 4.x supported
   
$handle   = curl_init($url);
    if (
false === $handle)
    {
        return
false;
    }
   
curl_setopt($handle, CURLOPT_HEADER, false);
   
curl_setopt($handle, CURLOPT_FAILONERROR, true);  // this works
   
curl_setopt($handle, CURLOPT_NOBODY, true);
   
curl_setopt($handle, CURLOPT_RETURNTRANSFER, false);
   
$connectable = curl_exec($handle);
   
curl_close($handle);   
    return
$connectable;
}
?>
ktcb123 at hotmail dot com 22-Oct-2007 12:26
For some reason, none of the url_exists() functions posted here worked for me, so here is my own tweaked version of it.

<?php
   
function url_exists($url){
       
$url = str_replace("http://", "", $url);
        if (
strstr($url, "/")) {
           
$url = explode("/", $url, 2);
           
$url[1] = "/".$url[1];
        } else {
           
$url = array($url, "/");
        }

       
$fh = fsockopen($url[0], 80);
        if (
$fh) {
           
fputs($fh,"GET ".$url[1]." HTTP/1.1\nHost:".$url[0]."\n\n");
            if (
fread($fh, 22) == "HTTP/1.1 404 Not Found") { return FALSE; }
            else { return
TRUE;    }

        } else { return
FALSE;}
    }
?>
guillermogomezruiz at gmail dot com 07-Sep-2007 04:08
I was having problems with the file_exists when using urls, so I made this function:

<?php
function file_exists_2($filePath)
{
    return (
$ch = curl_init($filePath)) ? @curl_close($ch) || true : false;
}
?>

Cheers!
bvazquez at siscomx dot com 04-Jul-2007 09:13
If you are trying to access a Windows Network Share you have to configure your WebServer with enough permissions for example:

$file = fopen("\\siscomx17\c\websapp.log",'r');

You will get an error telling you that the pathname doesnt exist this will be because Apache or IIS run as LocalSystem so you will have to enter to Services and configure Apache on "Open a session as" Create a new user that has enough permissions and also be sure that target share has the proper permissions.

Hope this save some hours of research to anyone.
vernon at kesnerdesigns dot net 10-May-2007 08:44
In response to seejohnrun's version to check if a URL exists. Even if the file doesn't exist you're still going to get 404 headers.  You can still use get_headers if you don't have the option of using CURL..

$file = 'http://www.domain.com/somefile.jpg';
$file_headers = @get_headers($file);
if($file_headers[0] == 'HTTP/1.1 404 Not Found') {
    $exists = false;
}
else {
    $exists = true;
}
earle dot west at transactionalweb dot com 14-Mar-2007 05:49
If the file being tested by file_exists() is a file on a symbolically-linked directory structure, the results depend on the permissions of the directory tree node underneath the linked tree.   PHP under a web server (i.e. apache) will respect permissions of the file system underneath the symbolic link, contrasting with PHP as a shell script which respects permissions of the directories that are linked (i.e. on top, and visible).  

This results in files that appear to NOT exist on a symbolic link, even though they are very much in existance and indeed are readable by the web server.
07-Jan-2006 01:08
I wrote this little handy function to check if an image exists in a directory, and if so, return a filename which doesnt exists e.g. if you try 'flower.jpg' and it exists, then it tries 'flower[1].jpg' and if that one exists it tries 'flower[2].jpg' and so on. It works fine at my place. Ofcourse you can use it also for other filetypes than images.

<?php
function imageExists($image,$dir) {

   
$i=1; $probeer=$image;

    while(
file_exists($dir.$probeer)) {
       
$punt=strrpos($image,".");
        if(
substr($image,($punt-3),1)!==("[") && substr($image,($punt-1),1)!==("]")) {
           
$probeer=substr($image,0,$punt)."[".$i."]".
           
substr($image,($punt),strlen($image)-$punt);
        } else {
           
$probeer=substr($image,0,($punt-3))."[".$i."]".
           
substr($image,($punt),strlen($image)-$punt);
        }
       
$i++;
    }
    return
$probeer;
}
?>
Fabrizio (staff at bibivu dot com) 21-Dec-2005 06:11
here a function to check if a certain URL exist:
<?php
   
function url_exists($url) {
       
$a_url = parse_url($url);
        if (!isset(
$a_url['port'])) $a_url['port'] = 80;
       
$errno = 0;
       
$errstr = '';
       
$timeout = 30;
        if(isset(
$a_url['host']) && $a_url['host']!=gethostbyname($a_url['host'])){
           
$fid = fsockopen($a_url['host'], $a_url['port'], $errno, $errstr, $timeout);
            if (!
$fid) return false;
           
$page = isset($a_url['path'])  ?$a_url['path']:'';
           
$page .= isset($a_url['query'])?'?'.$a_url['query']:'';
           
fputs($fid, 'HEAD '.$page.' HTTP/1.0'."\r\n".'Host: '.$a_url['host']."\r\n\r\n");
           
$head = fread($fid, 4096);
           
fclose($fid);
            return
preg_match('#^HTTP/.*\s+[200|302]+\s#i', $head);
        } else {
            return
false;
        }
    }
?>

in my CMS, I am using it with those lines:
<?php
       
if(!isset($this->f_exist[$image]['exist']))
            if(
strtolower(substr($fimage,0,4)) == 'http' || strtolower(substr($fimage,0,4)) == 'www.'){
                if(
strtolower(substr($image,0,4)) == 'www.'){
                   
$fimage = 'http://'.$fimage;
                   
$image = 'http://'.$image;
                }
               
$this->f_exist[$image]['exist'] = $this->url_exists($fimage); //for now
           
} else {
               
$this->f_exist[$image]['exist'] = ($fimage!='' && file_exists($fimage) && is_file($fimage) && is_readable($fimage) && filesize($fimage)>0);
            }
        }
?>
ihoss dot com at gmail dot com 19-Oct-2005 07:37
The following script checks if there is a file with the same name and adds _n to the end of the file name, where n increases. if img.jpg is on the server, it tries with img_0.jpg, checks if it is on the server and tries with img_1.jpg.
<?php
  $img
= "images/".$_FILES['bilde']['name'];
 
$t=0;
  while(
file_exists($img)){
   
$img = "images/".$_FILES['bilde']['name'];
   
$img=substr($img,0,strpos($img,"."))."_$t".strstr($img,".");
   
$t++;
  }
 
move_uploaded_file($_FILES['bilde']['tmp_name'], $img);
?>
tma at 2p dot cz 24-Aug-2005 01:47
If checking for a file newly created by an external program in Windows then file_exists() does not recognize it immediately.  Iy seems that a short timeout may be required.

<?
    $file = 'file.tmp';
    if ($h = popen("start \"bla\" touch $file", "r")) {
      pclose($h);
   // now I would like know if a file was created
   // note: usleep not supported
      $start = gettimeofday();  
      while (!file_exists(trim($file, " '\""))) {
        $stop = gettimeofday();
        if ( 1000000 * ($stop['sec'] - $start['sec']) + $stop['usec'] - $start['usec'] > 500000) break;  // wait a moment
     }

     if (file_exists($file))   // now should be reliable
?>
andrewNOSPAMPLEASE at abcd dot NOSPAMERSca 11-Feb-2005 05:29
file_exists will have trouble finding your file if the file permissions are not read enabled for 'other' when not owned by your php user. I thought I was having trouble with a directory name having a space in it (/users/andrew/Pictures/iPhoto Library/AlbumData.xml) but the reality was that there weren't read permissions on Pictures, iPhoto Library or AlbumData.xml. Once I fixed that, file_exists worked.
Nathaniel 08-Feb-2005 09:08
I spent the last two hours wondering what was wrong with my if statement: file_exists($file) was returning false, however I could call include($file) with no problem.

It turns out that I didn't realize that the php include_path value I had set in the .htaccess file didn't carry over to file_exists, is_file, etc.

Thus:

<?PHP
// .htaccess php_value include_path '/home/user/public_html/';

// includes lies in /home/user/public_html/includes/

//doesn't work, file_exists returns false
if ( file_exists('includes/config.php') )
{
     include(
'includes/config.php');
}

//does work, file_exists returns true
if ( file_exists('/home/user/public_html/includes/config.php') )
{
    include(
'includes/config.php');
}
?>

Just goes to show that "shortcuts for simplicity" like setting the include_path in .htaccess can just cause more grief in the long run.