PHPのお勉強!

PHP TOP

rename

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

renameファイルをリネームする

説明

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

fromto にリネームし、必要ならディレクトリを移動しようと試みます。 ファイル名の変更かつ to が存在する場合、上書きされます。 ディレクトリ名の変更かつ to が存在する場合、 この関数は警告を発します。

パラメータ

from

変更前の名前。

注意:

from で使用されるラッパーは、 to で使用するラッパーと適合 している必要があります

to

変更後の名前。

注意: Windows では、to が既に存在する場合、 そのファイルは書き込み可能でなければなりません。 書き込み可能でない場合、rename() は失敗し、 E_WARNING が発生します。

context

ストリームコンテキストリソース

戻り値

成功した場合に true を、失敗した場合に false を返します。

例1 rename() の例

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

参考

  • copy() - ファイルをコピーする
  • unlink() - ファイルを削除する
  • move_uploaded_file() - アップロードされたファイルを新しい位置に移動する

add a note

User Contributed Notes 27 notes

up
195
andrew at 21cv dot co dot uk
14 years ago
Code first, then explanation.

<?php

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

?>

That doesn't rename the file within the folder, as you might assume, instead, it moves the file to whatever the PHP working directory is... Chances are you'll not find it in your FTP tree. Instead, use the following:

<?php

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

?>
up
28
ben at indietorrent dot org
9 years ago
From the Changelog notes:

"Warnings may be generated if the destination filesystem doesn't permit chown() or chmod() system calls to be made on files — for example, if the destination filesystem is a FAT filesystem."

More explicitly, rename() may still return (bool) true, despite the warnings that result from the underlying calls to chown() or chmod(). This behavior can be misleading absent a deeper understanding of the underlying mechanics. To rename across filesystems, PHP "fakes it" by calling copy(), unlink(), chown(), and chmod() (not necessarily in that order). See PHP bug #50676 for more information.

On UNIX-like operating systems, filesystems may be mounted with an explicit uid and/or gid (for example, with mount options "uid=someuser,gid=somegroup"). Attempting to call rename() with such a destination filesystem will cause an "Operation not permitted" warning, even though the file is indeed renamed and rename() returns (bool) true.

This is not a bug. Either handle the warning as is appropriate to your use-case, or call copy() and then unlink(), which will avoid the doomed calls to chown() and chmod(), thereby eliminating the warning.
up
17
mike
11 years ago
Important note - rename() does NOT work for *directories* across filesystems or devices. Only *files*

You will get two warnings:
"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>"

The copy() mentioned I assume is C's copy() and not PHP's copy() function. There is an associated bug in the Ubuntu bug system for this as well, that was escalated to bugs.php.net:
https://bugs.php.net/bug.php?id=54097

The only workarounds right now I believe is using PHP copy($source, $dest) and then on success, PHP unlink($source), or doing system("mv $source $dest") which is hokey, and should be surrounded by quotes for paths with spaces or other shell metacharacters, and possibly escaped for security.
up
18
michael-nospam at sal dot mik dot hyperlink dot net dot au
25 years ago
Note, that on Unix, a rename is a beautiful way of getting atomic updates to files.

Just copy the old contents (if necessary), and write the new contents into a new file, then rename over the original file.

Any processes reading from the file will continue to do so, any processes trying to open the file while you're writing to it will get the old file (because you'll be writing to a temp file), and there is no "intermediate" time between there being a file, and there not being a file (or there being half a file).

Oh, and this only works if you have the temp file and the destination file on the same filesystem (eg. partition/hard-disk).
up
18
Whooptydoo
16 years ago
If by any chance you end up with something equivalent to this:

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

It returns true. It's not documented.
up
12
Martin Pelletier
13 years ago
rename() is working on Linux/UNIX but not working on Windows on a directory containing a file formerly opened within the same script. The problem persists even after properly closing the file and flushing the buffer.

<?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"); // will give a «permission denied» error
?>

Strangely it seem that the rename command is executed BEFORE the handle closing on Windows.

Inserting a sleep() command before the renaming cures the problem.

<?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); // this does the trick
rename ("./dir", ".dir2"); //no error
?>
up
13
pcdinh at phpvietnam dot net
15 years ago
For those who are still confused about the behavior of rename() in Linux and Windows (Windows XP) when target destination exists:

I have tested rename($oldName, $targetName) in PHP 5.3.0 and PHP 5.2.9 on both OS and find that if a file named $targetName does exist before, it will be overwritten with the content of $oldName
up
10
php at stock-consulting dot com
18 years ago
rename() fails with PHP4 and PHP5 under Windows if the destination file exists, regardless of file permission settings. I now use a function similar to that of ddoyle [at] canadalawbook [dot] ca, which first tries rename(), checks if it returned FALSE and then uses copy()/unlink() if it failed.

However, copy() is, unlike rename(), NOT useable for "atomic updates". Another process may actually access the destination file while copy() is working. In such a case, the other process with perceive the file as empty or with incomplete content ("half written").
up
1
lord dot dracon at gmail dot com
6 years ago
rename() function apparently doesn't move files larger than 4 GB, even though the filesystem supports, when the operating system is 32 bits.

Tested here with PHP 5.5.9 (x86), in Linux environment (Ubuntu 14.04.5 LTS i686), with source file (60 GB RAR file) in ext4 filesystem and destination is a external HD with NTFS filesystem. Only 4 GB was copied and RAR was corrupted: "Unexpected end of archive".

Not tested if rename() can move files larger than 4 GB in 64-bit environment.
up
3
David Thole (root at thedarktrumpet.com)
18 years ago
As of PHP 5.1.4 compiled on a mac, using rename with spaces one should just use the space. Take for example:

rename("/tmp/somefile.tar", "/mnt/laptop storage/somefile.tar");

If you use the backslash, like if you were cd-ing to the directory, rename will fail. Example:

rename("/tmp/somefile.tar", "/mnt/laptop\ storage/somefile.tar");

While not really a bug, it did confuse me for a little bit while working on a backup script.
up
4
tomfelker at gmail dot com
19 years ago
Actually, I'm pretty sure that rename follows the convention of *nix rename(2) in overwriting the destination if it exists atomically (meaning that no other process will see the destination cease to exist, even for an instant). This is useful because it allows you to build a file as a temp file, then rename it to where you want it to be, and nobody sees the file when it's half done.

Probably rename($old, $new) with an existing new was caused by permission problems. I bet the other problems you had were the result of not calling clearstatcache(), which can cause PHP to act like a file exists though it has since been deleted.
up
7
sophie at sitadelle dot com
21 years ago
Hello!
For unix/linux users: it is usefull to know that if you use rename() for a directory, the new one will be created with the current umask!
up
1
bcag2 at free dot fr
11 years ago
on windows (XP, vista, 7...) http://fr.wikipedia.org/wiki/Windows-1252", if your file name contains accent, it doesn't work basically. So use iconv function to convert from utf-8 to cp1252 as bellow :
<?php

$nomfichierinitial
=iconv("UTF-8", "CP1252", "C:\\wamp\\www\\tést.txt");
$nomfichierfinal="C:\\wamp\\www\\test.txt";
rename($nomfichierinitial, $nomfichierfinal);
?>
up
2
php-public at macfreek dot nl
19 years ago
It is unclear what encoding the arguments of rename should have; For PHP 4.3, on a HFS+ filesystems, rename() did not handle UTF-8 strings, and returned an error.
up
2
tbrillon at gmail dot com
19 years ago
I needed to move a file to another folder regardless if that file existed in the target already so I wrote a small piece to append a unique number to each file.

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

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

the output looks like this - 6881432893ad4925a1.70147481filename.txt

This also helps if you want different versions of the file stored.
up
2
ddoyle [at] canadalawbook [dot] ca
19 years ago
rename() definitely does not follow the *nix rename convention on WinXP with PHP 5. If the $newname exists, it will return FALSE and $oldname and $newname will remain in their original state. You can do something like this instead:

function rename_win($oldfile,$newfile) {
if (!rename($oldfile,$newfile)) {
if (copy ($oldfile,$newfile)) {
unlink($oldfile);
return TRUE;
}
return FALSE;
}
return TRUE;
}
up
2
andrew at iwebsolutions dot co dot uk
15 years ago
Note that this WILL NOT WORK if trying to rename a directory to a network share.

e.g.
rename('/home/user/me/dir1', '/mnt/shares/nfsmount/dir2')

will create a file called 'dir2' on the share and not a directory.

This caught me out and my (quickest) solution was to use an exec and mv command:

<?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";
}
?>
up
2
Eric (Themepark.com)
18 years ago
This was a fun one-- on Win XP, rename throws a "permission deined" if you try to rename across volumes.. i.e. rename("c:\windows\temp\x.txt", "g:\destination") will fail.
up
1
php at froghh dot de
18 years ago
Remark for "php at stock-consulting dot com"'s note:
This depends on the operating system.
On windows-systems you can't rename a file to an existing destination (ok, with tools you can - but they unlink the exisiting one before).