- 平台:Debian Wheezy 3.2.0-4-686-pae
- 编译器:GCC (Debian 4.7.2-5) 4.7.2 (Code::Blocks)
我想将文件从一个位置移动到另一个位置。没有什么比移动到不同的驱动器或不同的文件系统更复杂的了。我知道执行此操作的“标准”方法是简单地复制文件,然后删除原始文件。但我想要某种方式来保留文件的所有权、模式、上次访问/修改等。我假设我必须复制文件,然后编辑新文件的所有权、模式等,但我不知道该怎么做。
在 C 中移动文件的常用方法是使用rename(2),但有时会失败。
如果您不能使用rename(2)系统调用(例如因为源和目标在不同的文件系统上),您必须使用stat(2)查询源文件的大小、权限和其他元数据;复制read(2)、write(2)(使用几千字节的缓冲区)、open(2)、close(2)上的数据循环和使用chmod(2)、chown(2)、utime(2)的元数据. 您可能还关心使用getxattr(2)、setxattr(2)、listxattr(2)复制属性。您也可以在某些情况下使用sendfile(2),如评论 大卫·C·兰金。
如果源和目标位于不同的文件系统上,则无法使移动原子化并避免竞争条件(因此,如果可能,最好使用rename(2),因为根据其手册页它是原子的)。在移动操作期间始终可以修改源文件(由另一个进程)...
因此,移动文件的一种实用方法是首先尝试执行rename(2),如果失败EXDEV
(当oldpath和newpath不在同一个挂载的文件系统上时),那么您需要复制字节和元数据。几个库提供了这样做的函数,例如 Qt QFile::rename。
阅读Advanced Linux Programming - 并查看syscalls(2) - 了解更多信息(并尝试使用strace
一些mv
命令来了解它在做什么)。该书可免费合法下载(因此您可以在网上找到几本)。
该/bin/mv
命令(参见mv(1) )是自由软件GNU coreutils的一部分。您可以研究它的源代码,或者使用strace(1)来了解该命令的作用(就syscalls(2)而言)。在像sash或busybox这样的一些开源Unix shell中,可能是一个内置的 shell。另请参见path_resolution(7)和glob(7)。 mv
有一些微妙的极端情况(想象另一个进程或 pthread 在同一个文件系统、目录或文件上执行一些文件操作)。阅读一些操作系统教科书了解更多信息。
如果文件名包含奇怪的字符,例如or或换行符,或者以首字母. 请参阅errno(3)。tab
-
如果文件的原始位置和新位置位于同一文件系统上,则“移动”在概念上与“重命名”相同。
#include <stdio.h>
int rename (const char *oldname, const char *newname)