rename

(PHP 4, PHP 5, PHP 7, PHP 8)

rename重命名文件或目录

说明

rename(string $from, string $to, ?resource $context = null): bool

尝试将 from 重命名为 to,如果需要,在目录之间移动它。如果重命名文件并且 to 存在,它将被覆盖。如果重命名目录并且 to 存在,此函数将发出警告。

参数

from

旧名称。

注意:

from 中使用的包装器 *必须* 与在 to 中使用的包装器匹配。

to

新名称。

注意: 在 Windows 上,如果 to 已经存在,它必须是可写的。否则 rename() 失败并发出 E_WARNING

context

一个 上下文流 resource

返回值

成功时返回 true,失败时返回 false

示例

示例 #1 使用 rename() 的示例

<?php
rename
("/tmp/tmp_file.txt", "/home/user/login/docs/my_file.txt");
?>

参见

添加注释

用户贡献注释 27 notes

195
andrew at 21cv dot co dot uk
14 年前
代码优先,然后是解释。

<?php

rename
("/folder/file.ext", "newfile.ext");

?>

这不会像你可能假设的那样将文件重命名到文件夹中,而是将文件移动到 PHP 工作目录... 你很有可能在你的 FTP 树中找不到它。相反,使用以下代码

<?php

rename
("/folder/file.ext", "/folder/newfile.ext");

?>
28
ben at indietorrent dot org
9 年前
来自更改日志注释

"如果目标文件系统不允许对文件执行 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() 的注定调用,从而消除警告。
17
mike
10 年前
重要说明 - 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 元字符,并且可能为了安全起见而进行转义。
18
michael-nospam at sal dot mik dot hyperlink dot net dot au
24 年前
请注意,在 Unix 上,重命名是获得文件原子更新的绝佳方法。

只需复制旧内容(如果需要),并将新内容写入新文件,然后重命名覆盖原始文件。

任何从文件中读取的进程将继续这样做,任何在您写入文件时试图打开文件的进程将获得旧文件(因为您将写入临时文件),并且在存在文件和不存在文件之间没有“中间”时间(或存在半个文件)。

哦,这只有在你将临时文件和目标文件放在同一个文件系统(例如,分区/硬盘)上时才有效。
18
Whooptydoo
16 年前
如果你碰巧得到类似以下的东西

<?php
rename
('/foo/bar','/foo/bar');
?>

它返回 true。这没有被记录。
12
Martin Pelletier
13 年前
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"); // 无错误
?>
13
pcdinh at phpvietnam dot net
15 年前
对于那些仍然对 rename() 在 Linux 和 Windows(Windows XP)中目标目录存在时的行为感到困惑的人

我在 PHP 5.3.0 和 PHP 5.2.9 上测试了 rename($oldName, $targetName) 在两个操作系统上,发现如果之前存在名为 $targetName 的文件,它将被 $oldName 的内容覆盖
10
php at stock-consulting dot com
18 年前
如果目标文件存在,rename() 在 Windows 上的 PHP4 和 PHP5 中会失败,无论文件权限设置如何。我现在使用一个类似于 ddoyle [at] canadalawbook [dot] ca 的函数,它首先尝试 rename(),检查它是否返回 FALSE,然后在失败时使用 copy()/unlink()。

但是,与 rename() 不同,copy() 无法用于“原子更新”。另一个进程实际上可以在 copy() 工作时访问目标文件。在这种情况下,另一个进程会认为文件为空或内容不完整(“半写入”)。
1
lord dot dracon at gmail dot com
6 年前
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 的文件。
3
David Thole (root at thedarktrumpet.com)
17 年前
在 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");

虽然不算是真正的错误,但在编写备份脚本时确实让我困惑了一段时间。
4
tomfelker at gmail dot com
19 年前
实际上,我非常确定 rename 遵循 *nix rename(2) 的约定,在目标存在时原子地覆盖目标(意味着没有其他进程会看到目标停止存在,即使只是一瞬间)。这很有用,因为你可以将文件作为临时文件构建,然后将其重命名为你想要放置的位置,并且没有人会在它完成一半时看到该文件。

可能 rename($old, $new) 存在一个已存在的 new 是由权限问题引起的。我敢打赌你遇到的其他问题是由于没有调用 clearstatcache() 造成的,这会导致 PHP 认为文件存在,即使它已经被删除了。
7
sophie at sitadelle dot com
20 年前
您好!
对于 unix/linux 用户:知道如果你对目录使用 rename(),新目录将使用当前 umask 创建很有用!
1
bcag2 at free dot fr
11 年前
在 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);
?>
2
php-public at macfreek dot nl
18 年前
不清楚 rename 的参数应该是什么编码;对于 PHP 4.3,在 HFS+ 文件系统上,rename() 无法处理 UTF-8 字符串,并返回错误。
2
tbrillon at gmail dot com
18 年前
我需要将文件移动到另一个文件夹,无论该文件是否已存在于目标中,因此我编写了一小段代码,将唯一的数字附加到每个文件。

$rem = $_GET['file'];
$ticket = uniqid(rand(), true);

rename("$rem", "www/home/storefile/$ticket$rem");

输出如下 - 6881432893ad4925a1.70147481filename.txt

这也有助于你存储文件的不同版本。
2
ddoyle [at] canadalawbook [dot] ca
18 年前
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;
}
2
andrew at iwebsolutions dot co dot uk
15 年前
请注意,如果尝试将目录重命名为网络共享,这将不起作用。

例如
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";
}
?>
2
Eric (Themepark.com)
17 年前
这很有趣 - 在 Win XP 上,如果你尝试跨卷重命名,rename 会抛出“权限拒绝”.. 例如 rename("c:\windows\temp\x.txt", "g:\destination") 会失败。
1
php at froghh dot de
18 年前
关于“php at stock-consulting dot com”的说明
这取决于操作系统。
在 Windows 系统上,你无法将文件重命名为现有目标(好的,使用工具可以 - 但它们会在之前取消链接现有目标)。
1
dev at islam-soft dot com
17 年前
- 重命名文件的扩展名

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 留空 ''
1
Morteza
14 年前
此代码将特定目录中的所有文件和文件夹重命名为小写

<?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( '&nbsp;', ( $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 )

?>
-1
gssj85 at gmail dot com
1 年前
如果您重命名文件,它们的处理程序元数据将保持与之前相同。
1
PHP at Drarok dot com
18 年前
如 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 函数顶部打开的,而重命名是在底部。
0
tomv
7 年前
如果 $oldname 和 $newname 是指向同一文件的现有硬链接,则 rename() 不会执行任何操作,并返回成功状态。
(来自底层的 libc rename() 手册)
另一方面,“/bin/mv oldname newname” 会导致“oldname”被删除。
0
mike at mbfisher dot com
9 年前
[编辑说明:这之所以起作用是因为 SplFileObject 有 __toString() 方法,该方法返回文件路径]

请注意,您可以将 SplFileInfo 对象作为任一参数传递

<?php
# 假设当前目录中有一个名为 'foo' 的文件

rename('foo', new SplFileInfo('bar'));

# foo 现在是 bar!

rename(new SplFileInfo('bar'), 'foo');

# bar 现在又是 foo
?>
-1
Robert
10 年前
如果您对同一个文件使用 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' );

// 现在它正在工作。
?>
-1
pearcec at commnav dot com
23 年前
如果您将一个目录重命名为另一个已存在为空目录的目录,它不会报错。

这不是我预期的。

[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]$
To Top