rename()用来改变文件或者目录的位置
- rename(“y”, “z”); — 改变文件名字
- rename(“y”, “new/new”); — 改变文件名字和位置
NAME
rename, renameat, renameat2 - change the name or location of a file
SYNOPSIS
#include <stdio.h>
int rename(const char *oldpath, const char *newpath);
rename是如何将一个文件移动到另一个目录的呢?文件实际上不存在目录中,目录中存放的仅仅是它的链接。因此,rename将链接从一个目录移动到另一个目录:
内核是如何移动这些链接的呢?
- 复制链接到新的名字/位置
- 删除原来的链接。
Unix提供了系统调用link()和unlink()来完成这两个操作,因此,rename(“x”, “z”)相当于:
if(link("x", "z") != -1){
unlink("x");
}
只所以引入rename,是为了避免link和unlink的多线程竞争问题
命令mv就使用了rename()
rename()调用仅操作目录条目,而不移动文件数据。改名既不影响指向该文件的其他硬链接,也不应该持有该文件打开描述符的任何进程,因为这些文件描述符指向的是打开文件描述,(在调用 open()之后)与文件名并无瓜葛
以下规则适用于对rename()的调用
- 若newpath已经存在,则将其覆盖
- 若newpath与oldpath指向同一文件,则不发生变化(且调用成功)
- rename()系统调用对其两个参数中的符号链接均不进行解引用。
- 如果oldpath是一符号链接,那么将重命名该符号链接
- 如果newpath是一符号链接,那么将移除已有的符号链接,将其视为由oldpath 重命名而成的普通路径名
- 如果oldpath是文件而不是目录,那么就不能将newpath指定为一个目录的路径名(否则将 errno 置为 EISDIR)要想重命名一个文件到某一目录中(亦即将文件移到另一目录)newpath 必须包含新的文件名。如下调用既将一个文件移动到另一目录中,同时又将其改名
rename("sub1/x", "sub2/y");
- 若将oldpath指定为目录名,则意在重命名该目录。
- 这种情况下,必须保证newpath要么不存在,要么是一个空目录的名称。
- 无论 newpath 是一个已有文件还是一个非空目录,调用都将出错(分别将 errno 置为 ENOTDIR 和ENOTEMPTY)。
- 若 oldpath 是一目录,则 newpath 不能包含 oldpath 作为其目录前缀。例如,不能将/home/mtk 重命名为/home/mtk/bin(错误为 EINVAL)。
- ooldpath 和 newpath 所指代的文件必须位于同一文件系统。之所以如此,是因为目录内容由硬链接列表组成,且硬链接所指向的 i-node 与目录位于同一文件系统。如前所述rename()仅限于操作目录列表的内容。试图将一文件重命名至不同的文件系统将返回错误 EXDEV。(非要如此,必须从一个文件系统中将其文件内容复制到另一文件系统,然后再删除老文件。这正是 mv 命令的功能所在。)