Filesystem 函数
在线手册:中文 英文
PHP手册


Filesystem 函数
在线手册:中文 英文
PHP手册
PHP手册 - N: 删除文件

用户评论:

tornadossash at yahoo dot com (20-Dec-2011 11:12)

I also had the permission denied problem on Windows IIS7.0 (Vista). I could avoid this error if I give the user IUSR rights on the folder where the files are being written.

method:
folder: right click - properties - security - add user IUSR
give him full rights on this folder.

holdoffhunger at gmail dot com (11-Jun-2011 04:28)

There seems to be a lot of independent investigators here looking for buggy execution of this code (which actually be caused by or worsened by a Windows, Server operating system).  The main issue seems to be knowing for certain that the file was actually deleted, for example, not producing an error when a file isn't deleted on the command, or producing an error when the file actually is deleted.  Anyhow, the following is a tiny piece of code that absolutely deletes, even if it produces an error message, or never finishes, if it is unable to delete.

There are two outcomes: (1) It deletes the file, and continues happily along, error message, or not.  (2) It can't delete the file, can't modify the permissions, etc., and therefore, the script never completes, or it may throw some PHP errors at you eventually.

<?php

       
while(is_file($data_file_to_delete) == TRUE)
        {
           
chmod($data_file_to_delete, 0666);
           
unlink($data_file_to_delete);
        }

?>

webmaster at sebastiangrinke dot info (22-Feb-2011 01:57)

If you have a problem with unwriteable files test this ;)
Its a bit longer but it works really fine for me :)

<?php
public function delete_folder($tmp_path){
  if(!
is_writeable($tmp_path) && is_dir($tmp_path)){chmod($tmp_path,0777);}
   
$handle = opendir($tmp_path);
  while(
$tmp=readdir($handle)){
    if(
$tmp!='..' && $tmp!='.' && $tmp!=''){
         if(
is_writeable($tmp_path.DS.$tmp) && is_file($tmp_path.DS.$tmp)){
                
unlink($tmp_path.DS.$tmp);
         }elseif(!
is_writeable($tmp_path.DS.$tmp) && is_file($tmp_path.DS.$tmp)){
            
chmod($tmp_path.DS.$tmp,0666);
            
unlink($tmp_path.DS.$tmp);
         }
        
         if(
is_writeable($tmp_path.DS.$tmp) && is_dir($tmp_path.DS.$tmp)){
               
delete_folder($tmp_path.DS.$tmp);
         }elseif(!
is_writeable($tmp_path.DS.$tmp) && is_dir($tmp_path.DS.$tmp)){
               
chmod($tmp_path.DS.$tmp,0777);
               
delete_folder($tmp_path.DS.$tmp);
         }
    }
  }
 
closedir($handle);
 
rmdir($tmp_path);
  if(!
is_dir($tmp_path)){return true;}
  else{return
false;}
}
?>

dexen dot devries at gmail dot com (31-Dec-2010 09:28)

Deleted a large file but seeing no increase in free space or decrease of disk usage? Using UNIX or other POSIX OS?

The unlink() is not about removing file, it's about removing a file name. The manpage says: ``unlink - delete a name and possibly the file it refers to''.

Most of the time a file has just one name -- removing it will also remove (free, deallocate) the `body' of file (with one caveat, see below). That's the simple, usual case.

However, it's perfectly fine for a file to have several names (see the link() function), in the same or different directories. All the names will refer to the file body and `keep it alive', so to say. Only when all the names are removed, the body of file actually is freed.

The caveat:
A file's body may *also* be `kept alive' (still using diskspace) by a process holding the file open. The body will not be deallocated (will not free disk space) as long as the process holds it open. In fact, there's a fancy way of resurrecting a file removed by a mistake but still held open by a process...

federico at poisonfx dot com (06-Dec-2010 10:55)

Here the simplest way to delete files with mask

<?php
   $mask
= "*.jpg"
  
array_map( "unlink", glob( $mask ) );
?>

kgy (25-Nov-2010 10:34)

a note to the windows unlink problem. I had some code running on a linux server, unlinking files fine, but when i switched to my home computer running on windows, i suddenly had the unlink - permission denied problem. After trying everything (all those things with ownership, etc.), i found out that my file (a temporary file created with tempnam) was not closed, therefore it couldn't be unlinked. I hope this helps someone outthere :)

lpatrick (25-Oct-2010 10:08)

unlink can fail after using ODBC commands on the file (on Windows).

Neither <?php odbc_free_result($result); ?> nor <?php odbc_close($conn); unset($conn); ?> did the trick.

Only <?php odbc_close_all(); ?> released the file such that it could be deleted afterwards ...

zibi at nora dot pl (24-Sep-2010 03:01)

Shorter'n'faster version of Eddys "The shortest recursive delete possible"

function rrmdir($path)
{
  return is_file($path)?
    @unlink($path):
    array_map('rrmdir',glob($path.'/*'))==@rmdir($path)
  ;
}

layla_mwazza at hotmail dot com (12-Jul-2010 06:02)

May sound dumb, but it may help. Permission denied? Is the file still open in your script? Was for me...

mateusz at bkfmyjnie dot pl (06-May-2010 09:08)

If you're using PHP >= 5.0, consider using RecursiveDirectoryIterator (http://php.net/manual/en/class.recursivedirectoryiterator.php) class to iterate over all directories and files in a subtree in order to remove them.
Just be sure to use ->isDot() (http://php.net/manual/en/directoryiterator.isdir.php) to check for, and skip, dot and dot-dot (`.' and `..') directories :P

Eddy Vlad (24-Nov-2009 04:59)

The shortest recursive delete possible.

<?php
   
/**
     * Delete a file or recursively delete a directory
     *
     * @param string $str Path to file or directory
     */
   
function recursiveDelete($str){
        if(
is_file($str)){
            return @
unlink($str);
        }
        elseif(
is_dir($str)){
           
$scan = glob(rtrim($str,'/').'/*');
            foreach(
$scan as $index=>$path){
               
recursiveDelete($path);
            }
            return @
rmdir($str);
        }
    }
?>

reminder (12-Jun-2009 10:24)

careful with unlink...
"very unlikely" is not "impossible" : granted, it will happen.

1) "expected" : a typo and you'll get : unlink('/')
2) "very likely" : some of your files are writeable by anyone.
3) "possible" : you're backup drive is mounted and preserves the authorizations of the original files
4) "very unlikely" : that particular day, at that particular moment, the unlink function decided to work recursively

played all day long with ext3grep : no result.

Jon Hassall (16-Nov-2008 06:36)

Here is the recursive delete method made a little more readable:

<?php
/**
 * Recursively delete a directory
 *
 * @param string $dir Directory name
 * @param boolean $deleteRootToo Delete specified top-level directory as well
 */
function unlinkRecursive($dir, $deleteRootToo)
{
    if(!
$dh = @opendir($dir))
    {
        return;
    }
    while (
false !== ($obj = readdir($dh)))
    {
        if(
$obj == '.' || $obj == '..')
        {
            continue;
        }

        if (!@
unlink($dir . '/' . $obj))
        {
           
unlinkRecursive($dir.'/'.$obj, true);
        }
    }

   
closedir($dh);
   
    if (
$deleteRootToo)
    {
        @
rmdir($dir);
    }
   
    return;
}
?>

Anonymous (01-Nov-2008 02:13)

To unlink, the web server user must have write permissions to the directory.

Conversely, if a user has write permissions to a directory, it may delete files from that directory regardless of who owns them...

hi at hi dot hi (12-Oct-2008 04:19)

using this function with windows will generate an error, make sure to use is_file

garagod at gmail dot com (06-Oct-2008 06:36)

When I'm using unlink() or rename() with a SSH2.SFTP wrapper, both functions always return FALSE (but without a warning) even on success.

Example:

<?php
$connection
= ssh2_connect(SERVER_NAME, PORT);
ssh2_auth_password($connection, USERNAME, PASSWORD);
$sftp = ssh2_sftp($connection);

unlink("ssh2.sftp://$sftp/" . REMOTE_DIRECTORY . FILENAME); // returns FALSE on success and on failure

rename("ssh2.sftp://$sftp/" . REMOTE_DIRECTORY . OLD_FILENAME, "ssh2.sftp://$sftp/" . REMOTE_DIRECTORY . NEW_FILENAME); // returns FALSE on success and on failure
?>

http://www.paladinux.net (01-Oct-2008 04:59)

Under Windows System and Apache, denied access to file is an usual error to unlink file.
To delete file you must to change file's owern.
An example:

<?php
chown
($TempDirectory."/".$FileName,666); //Insert an Invalid UserId to set to Nobody Owern; 666 is my standard for "Nobody"
unlink($TempDirectory."/".$FileName);
?>

gotdalife at gmail dot com (25-Sep-2008 03:04)

To anyone who's had a problem with the permissions denied error, it's sometimes caused when you try to delete a file that's in a folder higher in the hierarchy to your working directory (i.e. when trying to delete a path that starts with "../").

So to work around this problem, you can use chdir() to change the working directory to the folder where the file you want to unlink is located.

<?php
    $old
= getcwd(); // Save the current directory
   
chdir($path_to_file);
   
unlink($filename);
   
chdir($old); // Restore the old working directory   
?>

southsentry at yahoo dot com (31-Aug-2008 06:23)

This is in response to alvaro at demogracia dot com

Yes, I found that out and have had to wrap it with is_file:

<?php
if(is_file("$file")) {
unlink("$file");
}
?>

PD (06-Aug-2008 01:07)

I have been working on some little tryout where a backup file was created before modifying the main textfile. Then when an error is thrown, the main file will be deleted (unlinked) and the backup file is returned instead.

Though, I have been breaking my head for about an hour on why I couldn't get my persmissions right to unlink the main file.

Finally I knew what was wrong: because I was working on the file and hadn't yet closed the file, it was still in use and ofcourse couldn't be deleted :)

So I thought of mentoining this here, to avoid others of making the same mistake:

<?php
// First close the file
fclose($fp);

// Then unlink :)
unlink($somefile);
?>

Guilherme Komel (30-Dec-2007 12:14)

I have founda that trying to delete a file using relative path like the example below does not work.

<?php
    $do
= unlink("../pics/$fileToDel");
    if(
$do=="1"){
        echo
"The file was deleted successfully.";
    } else { echo
"There was an error trying to delete the file."; }
?>

I did not work at all, instead what I had to do was:

<?php
    chdir
('../pics/');
   
$do = unlink($fileToDel);
    if(
$do=="1"){
        echo
"The file was deleted successfully.";
    } else { echo
"There was an error trying to delete the file."; }
?>

Then it worked !

ayor ATTTTT ayor.biz (20-Dec-2007 02:02)

ggarciaa's post above has already one small error, closedir has to be used even if $DeleteMe is false

<?php
// ggarciaa at gmail dot com (04-July-2007 01:57)
// I needed to empty a directory, but keeping it
// so I slightly modified the contribution from
// stefano at takys dot it (28-Dec-2005 11:57)
// A short but powerfull recursive function
// that works also if the dirs contain hidden files
//
// $dir = the target directory
// $DeleteMe = if true delete also $dir, if false leave it alone

function SureRemoveDir($dir, $DeleteMe) {
    if(!
$dh = @opendir($dir)) return;
    while (
false !== ($obj = readdir($dh))) {
        if(
$obj=='.' || $obj=='..') continue;
        if (!@
unlink($dir.'/'.$obj)) SureRemoveDir($dir.'/'.$obj, true);
    }

   
closedir($dh);
    if (
$DeleteMe){
        @
rmdir($dir);
    }
}

//SureRemoveDir('EmptyMe', false);
//SureRemoveDir('RemoveMe', true);

?>

james at NOSPAM dot telserco dot com (29-Sep-2007 03:10)

Cheap and dirty example for cleaning a directory of files so many seconds old.

        function cleantmp() {
                $seconds_old = 3600;
                $directory = "/var/tmp";

                if( !$dirhandle = @opendir($directory) )
                        return;

                while( false !== ($filename = readdir($dirhandle)) ) {
                        if( $filename != "." && $filename != ".." ) {
                                $filename = $directory. "/". $filename;

                                if( @filemtime($filename) < (time()-$seconds_old) )
                                        @unlink($filename);
                        }
                }
        }

rahulnvaidya at gmail dot com (03-Aug-2007 10:36)

ggarciaa's post above has one small error, it will ignore file and directory strings that are evaluated as false (ie. "0")

Fixed code is below (false !==)

<?php
// ggarciaa at gmail dot com (04-July-2007 01:57)
// I needed to empty a directory, but keeping it
// so I slightly modified the contribution from
// stefano at takys dot it (28-Dec-2005 11:57)
// A short but powerfull recursive function
// that works also if the dirs contain hidden files
//
// $dir = the target directory
// $DeleteMe = if true delete also $dir, if false leave it alone

function SureRemoveDir($dir, $DeleteMe) {
    if(!
$dh = @opendir($dir)) return;
    while (
false !== ($obj = readdir($dh))) {
        if(
$obj=='.' || $obj=='..') continue;
        if (!@
unlink($dir.'/'.$obj)) SureRemoveDir($dir.'/'.$obj, true);
    }
    if (
$DeleteMe){
       
closedir($dh);
        @
rmdir($dir);
    }
}

//SureRemoveDir('EmptyMe', false);
//SureRemoveDir('RemoveMe', true);

?>

ggarciaa at gmail dot com (04-Jul-2007 07:00)

<?php
// ggarciaa at gmail dot com (04-July-2007 01:57)
// I needed to empty a directory, but keeping it
// so I slightly modified the contribution from
// stefano at takys dot it (28-Dec-2005 11:57)
// A short but powerfull recursive function
// that works also if the dirs contain hidden files
//
// $dir = the target directory
// $DeleteMe = if true delete also $dir, if false leave it alone

function SureRemoveDir($dir, $DeleteMe) {
    if(!
$dh = @opendir($dir)) return;
    while ((
$obj = readdir($dh))) {
        if(
$obj=='.' || $obj=='..') continue;
        if (!@
unlink($dir.'/'.$obj)) SureRemoveDir($dir.'/'.$obj, true);
    }
    if (
$DeleteMe){
       
closedir($dh);
        @
rmdir($dir);
    }
}

//SureRemoveDir('EmptyMe', false);
//SureRemoveDir('RemoveMe', true);

?>

torch at torchsdomain dot com (22-Nov-2006 08:27)

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";
}

bmcouto at hotmail dot com (30-Sep-2006 09:30)

<?php
$myFile
= "testFile.txt";
$fh = fopen($myFile, 'w') or die("can't open file");
fclose($fh);
?>

Now to delete testFile.txt we simply run a PHP script that is located in the same directory. Unlink just needs to know the name of the file to start working its destructive magic.

<?php
$myFile
= "testFile.txt";
unlink($myFile);
?>

The testFile.txt should now be removed.

paul at pes-systems dot net (16-Aug-2006 06:27)

A work around for the Permission Denied problem.

I used ftp_connect() then ftp_delete() to erase files which unlink could not erase due to permision problems

bishop (05-Jun-2005 08:30)

<?php
/**
 * rm() -- Vigorously erase files and directories.
 *
 * @param $fileglob mixed If string, must be a file name (foo.txt), glob pattern (*.txt), or directory name.
 *                        If array, must be an array of file names, glob patterns, or directories.
 */
function rm($fileglob)
{
    if (
is_string($fileglob)) {
        if (
is_file($fileglob)) {
            return
unlink($fileglob);
        } else if (
is_dir($fileglob)) {
           
$ok = rm("$fileglob/*");
            if (!
$ok) {
                return
false;
            }
            return
rmdir($fileglob);
        } else {
           
$matching = glob($fileglob);
            if (
$matching === false) {
               
trigger_error(sprintf('No files match supplied glob %s', $fileglob), E_USER_WARNING);
                return
false;
            }      
           
$rcs = array_map('rm', $matching);
            if (
in_array(false, $rcs)) {
                return
false;
            }
        }      
    } else if (
is_array($fileglob)) {
       
$rcs = array_map('rm', $fileglob);
        if (
in_array(false, $rcs)) {
            return
false;
        }
    } else {
       
trigger_error('Param #1 must be filename or glob pattern, or array of filenames or glob patterns', E_USER_ERROR);
        return
false;
    }

    return
true;
}
?>

jchase at solidmark dot com (21-May-2005 06:05)

[Editor's note: A suggestion for a work-around was submitted by argistof at gmail dot com: You can use the recursive option (see man chmod) when chmodding, for instance 'chmod 777 directory/ -R'. Be aware though, this will change the permissions of all files and folders in the diectory.]

Just a note which you probably all know, but I didn't, and it might save another poor sap some unnecessary time:

I was doing unlink() and fopen() on a file and got a permission denied error, even after chmoding the file to 0777. 

The folder that contains the file must ALSO have write permission.  Took a headache to find this out. 

Hope this helps someone :)

ashley at semantic dot org (02-Apr-2005 10:50)

Actually you should use "@unlink" rather than testing with file_exists. The former is atomic, whereas the latter can break if you can't guarantee only one process will try to delete a given file at a time.

dagski_AT_gmail_DOT_com (07-Feb-2005 06:19)

before you could unlink a file created which uses a handle e.g.,

$handle = sqlite('temp.db');

unset($handle); first befofe
unlink($handle);

to avoide permission denied error.

chris at vibenewmedia dot com (14-Sep-2004 06:54)

To delete all files of a particular extension, or infact, delete all with wildcard, a much simplar way is to use the glob function.  Say I wanted to delete all jpgs .........

<?php

foreach (glob("*.jpg") as $filename) {
   echo
"$filename size " . filesize($filename) . "\n";
  
unlink($filename);
}

?>

pc AT newagelab DOT com DOT ua (08-Sep-2004 04:22)

To delete files using wildcards:

<?
function delfile($str)
{
    foreach(glob($str) as $fn) {
        unlink($fn);
    }
}
?>