代码优先,然后是解释。
<?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 文件系统。"
更明确地说,rename() 仍然可能返回 (bool) true,尽管由于对 chown() 或 chmod() 的底层调用导致了警告。这种行为在没有深入了解底层机制的情况下可能会造成误导。为了在文件系统之间重命名,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(): The first argument to copy() function cannot be a directory in <whatever> on line <whatever>"
"PHP Warning: rename(t2,/var/run/test/t2): Invalid cross-device link in <whatever> on line <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"); // 无错误
?>
对于那些仍然对 rename() 在 Linux 和 Windows(Windows XP)中目标目录存在时的行为感到困惑的人
我在 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() 函数显然不能移动大于 4 GB 的文件,即使文件系统支持,当操作系统是 32 位时。
在 Linux 环境(Ubuntu 14.04.5 LTS i686)中,使用 PHP 5.5.9 (x86) 在此进行了测试,源文件(60 GB RAR 文件)位于 ext4 文件系统中,目标是具有 NTFS 文件系统的外部 HD。仅复制了 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") 会失败。
关于“php at stock-consulting dot com”的说明
这取决于操作系统。
在 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)) { # Look at only files with a pre-defined extension
$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' ); // Permission Denied!
?>
只需关闭句柄即可解决此问题
<?php
$fileHand = fopen('tempFile.txt', 'r');
fclose($fileHand);
rename( 'tempFile.txt', 'tempFile2.txt' );
?>
这让我挠头好一阵子,因为句柄是在 marge 函数顶部打开的,而重命名是在底部。
如果 $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
total 12
drwxr-xr-x 3 pearcec commnav 4096 Jun 15 13:17 .
drwxr-xr-x 18 pearcec commnav 4096 Jun 15 13:15 ..
drwxr-xr-x 2 pearcec commnav 4096 Jun 15 13:16 test2
[pearcec@abe tmp]$ ls -la test2/
total 8
drwxr-xr-x 2 pearcec commnav 4096 Jun 15 13:16 .
drwxr-xr-x 3 pearcec commnav 4096 Jun 15 13:17 ..
-rw-r--r-- 1 pearcec commnav 0 Jun 15 13:16 test
[pearcec@abe tmp]$