这将在一行代码中删除与模式匹配的目录中的所有文件。
<?php array_map('unlink', glob("some/dir/*.txt")); ?>
(PHP 4, PHP 5, PHP 7, PHP 8)
unlink — 删除文件
删除 filename
。类似于 Unix C 的 unlink() 函数。如果失败,将生成一个 E_WARNING
级别的错误。
版本 | 描述 |
---|---|
7.3.0 | 在 Windows 上,现在可以 unlink() 正在使用的文件的句柄,而以前会失败。但是,在所有句柄关闭之前,仍然无法重新创建已删除的文件。 |
示例 #1 基本的 unlink() 使用方法
<?php
$fh = fopen('test.html', 'a');
fwrite($fh, '<h1>Hello world!</h1>');
fclose($fh);
unlink('test.html');
?>
这将在一行代码中删除与模式匹配的目录中的所有文件。
<?php array_map('unlink', glob("some/dir/*.txt")); ?>
删除了一个大文件,但没有看到可用空间增加或磁盘使用量减少?使用 UNIX 或其他 POSIX 操作系统?
unlink() 不是关于删除文件,而是关于删除文件名。手册页写道:“unlink - 删除一个名称,可能还会删除它引用的文件”。
大多数情况下,一个文件只有一个名称 - 删除它也会删除(释放,解除分配)文件的“主体”(有一个例外,见下文)。这是简单、常见的情况。
但是,一个文件可以拥有多个名称(参见 link() 函数),在相同或不同的目录中。所有名称都将引用文件主体并“使它保持活动状态”,可以说。只有当所有名称都被删除时,文件的主体才会被真正释放。
例外情况
文件的“主体”也可能被一个持有该文件打开的进程“保持活动状态”(仍在使用磁盘空间)。只要该进程持有该文件打开,该主体就不会被解除分配(不会释放磁盘空间)。事实上,有一种巧妙的方法可以恢复因错误删除但仍被进程持有的文件…
unlink($fileName); 对我来说失败了。
然后我尝试使用 realpath($fileName) 函数,如下所示
unlink(realpath($fileName)); 它起作用了
只是发布它,以防有人发现它有用。
以下是删除带掩码的文件的最简单方法
<?php
$mask = "*.jpg"
array_map( "unlink", glob( $mask ) );
?>
要删除所有特定扩展名的文件,或者事实上,删除所有带通配符的文件,一种更简单的方法是使用 glob 函数。假设我想删除所有 jpg 文件.........
<?php
foreach (glob("*.jpg") as $filename) {
echo "$filename size " . filesize($filename) . "\n";
unlink($filename);
}
?>
我一直在做一些小测试,在修改主文本文件之前创建备份文件。然后,当抛出错误时,主文件将被删除(取消链接),并且备份文件将被返回。
不过,我一直苦苦思索了一个小时,为什么我无法获得正确的权限来取消链接主文件。
最后我明白了问题所在:因为我在使用该文件,并且还没有关闭该文件,所以它仍在使用中,当然无法删除 :)。
所以我想在这里提一下,以避免其他人犯同样的错误。
<?php
// 首先关闭文件
fclose($fp);
// 然后取消链接 :)
unlink($somefile);
?>
对于遇到“权限被拒绝”错误的任何人来说,这有时是由于尝试删除位于工作目录更高层次的文件夹中的文件而导致的(例如,当尝试删除以“../”开头的路径时)。
因此,要解决这个问题,可以使用 chdir() 将工作目录更改为要取消链接的文件所在的文件夹。
<?php
$old = getcwd(); // 保存当前目录
chdir($path_to_file);
unlink($filename);
chdir($old); // 恢复旧的工作目录
?>
这可能看起来很明显,但我为此问题抓破了头皮 - 确保您尝试删除的文件当前没有被使用。我有一个脚本应该解析一个文本文件并在完成后删除它,但我一直收到“权限被拒绝”错误,因为我没有显式关闭文件,因此它在技术上仍然被“使用”,即使解析已完成。
如果您正在寻找递归取消链接
<?php
/**
* 删除文件或目录
* 如果需要,自动遍历目录。
* 备注:未测试过自引用符号链接,可能导致无限递归,我不确定。
*
* @param string $cmd
* @throws \RuntimeException 如果 unlink 失败
* @throws \RuntimeException 如果 rmdir 失败
* @return void
*/
function unlinkRecursive(string $path, bool $verbose = false): void
{
if (!is_readable($path)) {
return;
}
if (is_file($path)) {
if ($verbose) {
echo "unlink: {$path}\n";
}
if (!unlink($path)) {
throw new \RuntimeException("Failed to unlink {$path}: " . var_export(error_get_last(), true));
}
return;
}
$foldersToDelete = array();
$filesToDelete = array();
// 我们应该在深入遍历之前扫描整个目录,以避免对每个目录打开句柄:
// 在非常大的目录树上,如果你有太多打开的目录句柄,实际上会遇到操作系统错误。
foreach (new DirectoryIterator($path) as $fileInfo) {
if ($fileInfo->isDot()) {
continue;
}
if ($fileInfo->isDir()) {
$foldersToDelete[] = $fileInfo->getRealPath();
} else {
$filesToDelete[] = $fileInfo->getRealPath();
}
}
unset($fileInfo); // 释放文件句柄
foreach ($foldersToDelete as $folder) {
unlinkRecursive($folder, $verbose);
}
foreach ($filesToDelete as $file) {
if ($verbose) {
echo "unlink: {$file}\n";
}
if (!unlink($file)) {
throw new \RuntimeException("Failed to unlink {$file}: " . var_export(error_get_last(), true));
}
}
if ($verbose) {
echo "rmdir: {$path}\n";
}
if (!rmdir($path)) {
throw new \RuntimeException("Failed to rmdir {$path}: " . var_export(error_get_last(), true));
}
}
?>
在 OSX 上,当你遇到 "Permission Denied" 错误时,请确保该目录对执行 php 的用户有写入权限。
此外,如果你依赖 ACL,并且想要删除文件或符号链接,包含目录需要具有 "delete_child" 权限才能删除内部内容。如果你只向文件夹授予 "delete" 权限,则可以删除容器文件夹本身,但不能删除内部对象。
unlink 的工作原理与 nix 系统上的 rm 命令或 windows 上的 del 命令相同,它不会解析文件,而是删除给定的确切路径,即使该路径只是一个链接。
例如
/var/www/test/index.php = symlink(/home/test/www/index.php)
<?php
unlink("/var/www/test/index.php");
?>
只会删除链接,而不是原始文件,而
<?php
unlink("/home/test/www/index.php");
?>
会取消链接原始文件路径并破坏符号链接,并允许系统覆盖,因为文件系统不再知道文件的位置。
通过掩码删除文件的最佳方法如下所示
<?php
array_walk(glob('/etc/*'), 'unlink');
?>
不要使用下面提到的 array_map - 它的目的是处理给定数组中的值并收集回调函数返回的数据。所以,array_map 比 array_walk 速度更慢,并且会使用额外的内存。