先代码,再解释。
<?php
rename ("/folder/file.ext", "newfile.ext");
?>
这不会像你想象的那样重命名文件夹中的文件,而是将文件移动到 PHP 的工作目录...很有可能你在 FTP 树中找不到它。相反,请使用以下方法
<?php
rename ("/folder/file.ext", "/folder/newfile.ext");
?>
(PHP 4, PHP 5, PHP 7, PHP 8)
rename — 重命名文件或目录
尝试将 from
重命名为 to
,如有必要,在目录之间移动它。如果重命名文件且 to
存在,则将被覆盖。如果重命名目录且 to
存在,则此函数将发出警告。
示例 #1 使用 rename() 的示例
<?php
rename("/tmp/tmp_file.txt", "/home/user/login/docs/my_file.txt");
?>
先代码,再解释。
<?php
rename ("/folder/file.ext", "newfile.ext");
?>
这不会像你想象的那样重命名文件夹中的文件,而是将文件移动到 PHP 的工作目录...很有可能你在 FTP 树中找不到它。相反,请使用以下方法
<?php
rename ("/folder/file.ext", "/folder/newfile.ext");
?>
来自更改日志说明
"如果目标文件系统不允许对文件进行 chown() 或 chmod() 系统调用 - 例如,如果目标文件系统是 FAT 文件系统,则可能会生成警告。"
更明确地说,即使由于对 chown() 或 chmod() 的底层调用而导致警告,rename() 仍然可能返回 (bool) true。在没有深入了解底层机制的情况下,这种行为可能会产生误导。为了跨文件系统重命名,PHP 通过调用 copy()、unlink()、chown() 和 chmod()(不一定按此顺序)来“伪造”它。有关更多信息,请参阅 PHP 错误 #50676。
在类 Unix 操作系统上,文件系统可以以显式的 uid 和/或 gid 挂载(例如,使用挂载选项“uid=someuser,gid=somegroup”)。尝试对这样的目标文件系统调用 rename() 将导致“操作不被允许”警告,即使文件确实已重命名并且 rename() 返回 (bool) true。
这不是错误。根据您的用例,要么处理警告,要么调用 copy() 然后 unlink(),这将避免对 chown() 和 chmod() 的注定调用,从而消除警告。
重要说明 - rename() 对于跨文件系统或设备的*目录*不起作用。仅适用于*文件*
您将收到两个警告
"PHP Warning: rename(): copy() 函数的第一个参数不能是 <whatever> 中的目录在第 <whatever> 行"
"PHP Warning: rename(t2,/var/run/test/t2): <whatever> 中的无效跨设备链接在第 <whatever> 行"
我假设提到的 copy() 是 C 的 copy(),而不是 PHP 的 copy() 函数。Ubuntu 错误系统中也存在与此相关的错误,并且已升级到 bugs.php.net
https://bugs.php.net/bug.php?id=54097
目前,我相信唯一的方法是使用 PHP copy($source, $dest),然后在成功后使用 PHP unlink($source),或者执行 system("mv $source $dest"),这很笨拙,并且应该用引号括起来以处理路径中的空格或其他 shell 元字符,并且可能需要转义以确保安全。
请注意,在 Unix 上,重命名是获取文件原子更新的一种好方法。
只需复制旧内容(如果需要),并将新内容写入新文件,然后重命名原始文件。
任何从该文件读取的进程将继续这样做,任何在您写入该文件时尝试打开该文件的进程都将获取旧文件(因为您将写入临时文件),并且在文件存在和文件不存在(或文件存在一半)之间没有“中间”时间。
哦,这仅在您在同一文件系统(例如分区/硬盘)上拥有临时文件和目标文件时才有效。
rename() 在 Linux/UNIX 上有效,但在同一脚本中先前打开的文件所在的目录的 Windows 上无效。即使在正确关闭文件并刷新缓冲区后,问题仍然存在。
<?php
$fp = fopen ("./dir/ex.txt" , "r+");
$text = fread($fp, filesize("../dir/ex.txt"));
ftruncate($fp, 0);
$text2 = "some value";
fwrite ($fp, $text2 );
fflush($fp);
fclose ($fp);
if (is_resource($fp))
fclose($fp);
rename ("./dir", ".dir2"); // 将会返回「权限被拒绝」错误
?>
奇怪的是,在 Windows 上,rename 命令似乎在句柄关闭之前就被执行了。
在重命名之前插入一个 sleep() 命令可以解决这个问题。
<?php
$fp = fopen ("./dir/ex.txt" , "r+");
$text = fread($fp, filesize("../dir/ex.txt"));
ftruncate($fp, 0);
$text2 = "some value";
fwrite ($fp, $text2 );
fflush($fp);
fclose ($fp);
if (is_resource($fp))
fclose($fp);
sleep(1); // 这解决了问题
rename ("./dir", ".dir2"); // 没有错误
?>
对于那些仍然对 Linux 和 Windows(Windows XP)中 rename() 在目标目的地存在时的行为感到困惑的人
我在 PHP 5.3.0 和 PHP 5.2.9 上的两个操作系统上测试了 rename($oldName, $targetName),发现如果名为 $targetName 的文件之前存在,它将被 $oldName 的内容覆盖。
如果目标文件存在,则 rename() 在 Windows 下使用 PHP4 和 PHP5 会失败,无论文件权限设置如何。我现在使用一个类似于 ddoyle[at]canadalawbook[dot]ca 的函数,该函数首先尝试 rename(),检查它是否返回 FALSE,然后在失败时使用 copy()/unlink()。
但是,与 rename() 不同,copy() 不能用于“原子更新”。另一个进程实际上可能会在 copy() 工作时访问目标文件。在这种情况下,另一个进程会将文件视为为空或内容不完整(“半写”)。
rename() 函数显然无法移动大于 4GB 的文件,即使文件系统支持,当操作系统为 32 位时。
此处在 PHP 5.5.9 (x86) 中,在 Linux 环境 (Ubuntu 14.04.5 LTS i686) 中进行了测试,源文件 (60 GB RAR 文件) 在 ext4 文件系统中,目标是具有 NTFS 文件系统的外部硬盘驱动器。仅复制了 4 GB,并且 RAR 已损坏:“意外的归档文件结束”。
未测试 rename() 是否可以在 64 位环境中移动大于 4 GB 的文件。
从在 Mac 上编译的 PHP 5.1.4 开始,使用带有空格的 rename 时,应该只使用空格。例如
rename("/tmp/somefile.tar", "/mnt/laptop storage/somefile.tar");
如果您使用反斜杠,就像您要 cd 到目录一样,rename 将失败。例如
rename("/tmp/somefile.tar", "/mnt/laptop\ storage/somefile.tar");
虽然不是真正的错误,但在处理备份脚本时确实让我困惑了一段时间。
实际上,我非常确定 rename 遵循 *nix rename(2) 的约定,如果目标文件存在,则以原子方式覆盖目标文件(意味着没有其他进程会看到目标文件停止存在,即使只是一瞬间)。这很有用,因为它允许您将文件构建为临时文件,然后将其重命名为您想要的位置,并且没有人会在文件完成一半时看到它。
可能 rename($old, $new) 以及已存在的 new 是由权限问题引起的。我敢打赌,您遇到的其他问题是由于没有调用 clearstatcache() 导致的,这会导致 PHP 认为文件存在,尽管它已被删除。
在 Windows(XP、Vista、7...)http://fr.wikipedia.org/wiki/Windows-1252 上,如果您的文件名包含重音符号,则它基本上不起作用。因此,请使用 iconv 函数将 UTF-8 转换为 cp1252,如下所示
<?php
$nomfichierinitial=iconv("UTF-8", "CP1252", "C:\\wamp\\www\\tést.txt");
$nomfichierfinal="C:\\wamp\\www\\test.txt";
rename($nomfichierinitial, $nomfichierfinal);
?>
尚不清楚 rename 的参数应该使用什么编码;对于 PHP 4.3,在 HFS+ 文件系统上,rename() 无法处理 UTF-8 字符串,并返回错误。
我需要将文件移动到另一个文件夹,无论该文件是否已存在于目标文件夹中,所以我编写了一小段代码,为每个文件附加一个唯一的数字。
$rem = $_GET['file'];
$ticket = uniqid(rand(), true);
rename("$rem", "www/home/storefile/$ticket$rem");
输出如下 - 6881432893ad4925a1.70147481filename.txt
如果您希望存储文件的不同版本,这也有帮助。
rename() 在 WinXP 上使用 PHP 5 时肯定不遵循 *nix rename 约定。如果 $newname 存在,它将返回 FALSE,并且 $oldname 和 $newname 将保持其原始状态。您可以改为执行以下操作
function rename_win($oldfile,$newfile) {
if (!rename($oldfile,$newfile)) {
if (copy ($oldfile,$newfile)) {
unlink($oldfile);
return TRUE;
}
return FALSE;
}
return TRUE;
}
请注意,如果尝试将目录重命名为网络共享,则这将不起作用。
例如
rename('/home/user/me/dir1', '/mnt/shares/nfsmount/dir2')
将在共享上创建一个名为“dir2”的文件,而不是目录。
这让我措手不及,我的(最快)解决方案是使用 exec 和 mv 命令
<?php
$cmd = 'mv "/home/user/me/dir1" "/mnt/shares/nfsmount/dir2"';
exec($cmd, $output, $return_val);
if ($return_val == 0) {
echo "success";
} else {
echo "failed";
}
?>
这个很有趣——在 Win XP 上,如果您尝试跨卷重命名,rename 会抛出“权限被拒绝”错误。即 rename("c:\windows\temp\x.txt", "g:\destination") 将失败。
关于“[email protected]”的注释
这取决于操作系统。
在 Windows 系统上,您无法将文件重命名为现有的目标(好的,使用工具可以 - 但它们会在重命名之前取消链接现有的文件)。
- 重命名文件的扩展名
changeext($directory, $ext1, $ext2, $verbose)
我编写了此函数来重命名文件夹及其内部子文件夹中某些文件的扩展名..
参数 1:目录名称
参数 2:我们要替换的第一个扩展名
参数 3:文件的新的扩展名
要简单使用,请调用函数
changeext('dir', 'html', 'php', 'false');
将目录 dir 中扩展名为 html 的每个文件名更改为 php
<?php
function changeext($directory, $ext1, $ext2, $verbose = false) {
$num = 0;
if($curdir = opendir($directory)) {
while($file = readdir($curdir)) {
if($file != '.' && $file != '..') {
$srcfile = $directory . '/' . $file;
$string = "$file";
$str = strlen($ext1);
$str++;
$newfile = substr($string, 0, -$str);
$newfile = $newfile.'.'.$ext2;
$dstfile = $directory . '/' . $newfile;
if (eregi("\.$ext1",$file)) { # 仅查看具有预定义扩展名的文件
$fileHand = fopen($srcfile, 'r');
fclose($fileHand);
rename($srcfile, $dstfile );
}
if(is_dir($srcfile)) {
$num += changeext($srcfile, $ext1, $ext2, $verbose);
}
}
}
closedir($curdir);
}
return $num;
}
changeext('dir', 'html', 'php', 'false');
?>
要删除文件的扩展名,只需将参数 $ext2 留空 ''
此代码将特定目录中的所有文件和文件夹重命名为小写。
<?php
$path = "my_doc";
function getDirectory( $path = '.', $level = 0 ){
$ignore = array( 'cgi-bin', '.', '..' );
$dh = @opendir( $path );
while( false !== ( $file = readdir( $dh ) ) )
{
if( !in_array( $file, $ignore ) )
{
$spaces = str_repeat( ' ', ( $level * 4 ) );
if( is_dir( "$path/$file" ) )
{
echo "<strong>$spaces $file</strong><br />";
rename($path."\\".$file, strtolower($path."\\".$file));
getDirectory( "$path/$file", ($level+1) );
}
else {
echo "$spaces $file<br />";
rename($path."\\".$file, strtolower($path."\\".$file));
}
}
}
closedir( $dh );
}
getDirectory( $path , 0 )
?>
如 unlink() 页面所述
在重命名文件之前,必须释放对该文件的所有句柄(至少在 Windows 上如此)。
这将不起作用,您将收到权限被拒绝错误
<?php
$fileHand = fopen('tempFile.txt', 'r');
rename( 'tempFile.txt', 'tempFile2.txt' ); // 权限被拒绝!
?>
只需关闭句柄即可解决此问题
<?php
$fileHand = fopen('tempFile.txt', 'r');
fclose($fileHand);
rename( 'tempFile.txt', 'tempFile2.txt' );
?>
这让我思考了很长时间,因为句柄是在合并函数的顶部打开的,而重命名是在底部进行的。
如果 $oldname 和 $newname 是引用同一文件的现有硬链接,则 rename() 不执行任何操作,并返回成功状态。
(来自底层 libc rename() 手册)
另一方面,“/bin/mv oldname newname”会导致“oldname”被删除。
[编辑注:这之所以有效是因为 SplFileObject 具有 __toString() 方法,该方法返回文件路径]
请注意,您可以将 SplFileInfo 对象作为任一参数传递
<?php
# 假设当前目录中有一个文件“foo”
rename('foo', new SplFileInfo('bar'));
# foo 现在是 bar!
rename(new SplFileInfo('bar'), 'foo');
# bar 现在又变成了 foo
?>
如果您对要重命名的同一文件使用 SplFileObject
则必须首先删除 SplFileObject 对象。
<?php
$filePath = 'testFile.txt';
$fileObj = new SplFileObject( $filePath );
rename( $filePath, 'newName.txt' );
// 您将收到 - 权限被拒绝错误
$filePath = 'testFile.txt';
$fileObj = new SplFileObject( 'filePath.txt' );
$fileObj = null;
rename( $filePath, 'newName.txt' );
// 现在它可以工作了。
?>
如果您将一个目录重命名为另一个目录,而第二个目录作为空目录存在,它不会报错。
与我预期的不符。
[pearcec@abe tmp]$ mkdir test1
[pearcec@abe tmp]$ mkdir test2
[pearcec@abe tmp]$ touch test1/test
[pearcec@abe tmp]$ php
<?php
rename("test1","test2");
?>
X-Powered-By: PHP/4.0.5
Content-type: text/html
[pearcec@abe tmp]$ ls -al
总计 12
drwxr-xr-x 3 pearcec commnav 4096 6月 15 13:17 .
drwxr-xr-x 18 pearcec commnav 4096 6月 15 13:15 ..
drwxr-xr-x 2 pearcec commnav 4096 6月 15 13:16 test2
[pearcec@abe tmp]$ ls -la test2/
总计 8
drwxr-xr-x 2 pearcec commnav 4096 6月 15 13:16 .
drwxr-xr-x 3 pearcec commnav 4096 6月 15 13:17 ..
-rw-r--r-- 1 pearcec commnav 0 6月 15 13:16 test
[pearcec@abe tmp]$