在C中移动Linux上的文件

Joh*_*inz 11 c linux

  • 平台:Debian Wheezy 3.2.0-4-686-pae
  • 编译器:GCC(Debian 4.7.2-5)4.7.2(代码::块)

我想将文件从一个位置移动到另一个位置.没有什么比移动到不同的驱动器或不同的文件系统更复杂.我知道执行此操作的"标准"方法是简单地复制文件然后删除原始文件.但我想要一些方法来保留文件的所有权,模式,上次访问/修改等.我假设我将不得不复制文件,然后编辑新文件的所有权,模式等,但我不知道如何做到这一点.

Bas*_*tch 17

如果你不能使用rename(2)系统调用(例如因为源和目标在不同的文件系统上),你必须用stat(2)查询源文件的大小,权限和其他元数据; 使用read(2),write(2)(使用几千字节的缓冲区),open(2),close(2)以及使用chmod(2),chown(2),utime(2)的元数据来复制数据.您可能还关心使用getxattr(2),setxattr(2),listxattr(2)复制属性

如果源和目标位于不同的文件系统上,则无法使原子移动并避免竞争条件(因此,如果可能,最好使用rename(2),因为根据其手册页它是原子的).在移动操作期间,始终可以修改源文件(通过其他进程)...

阅读高级Linux编程以获取更多信息(并尝试使用EXDEV某些strace命令来了解它正在做什么).

  • 对于Linux,[sendfile](http://man7.org/linux/man-pages/man2/sendfile.2.html)提供了一种跨文件系统边界进行复制的方法,该方法比“读取”,“写入”更有效。原始的“ sendfile”的大小限制为“ 0x7ffff000(2,147,479,552)”字节,但是Linux还为“ offset”参数添加了“ sendfile64”包装器,该包装器具有更宽的类型。 (2认同)

kgr*_*ney 16

如果文件的原始位置和新位置在同一文件系统上,则"移动"在概念上与" 重命名 " 相同.

#include <stdio.h>

int rename (const char *oldname, const char *newname)
Run Code Online (Sandbox Code Playgroud)

  • @BasileStarynkevitch - 重命名在文件系统级别是原子的.它立即是oldname或newname.什么atk说,如果你有代码通过名称(char*)找到一个文件,然后重命名它(用char*),你不是100%肯定你第一次找到的文件是你的文件是同一个重命名,如果另一个进程正在更改您的文件. (4认同)
  • @atk:你为什么认为`rename(2)`很危险?我相信它是原子的,因为它是一个系统调用,它的`man`页面提到了原子性! (3认同)
  • 您可能想要告诉OP如何检测两个文件是否在同一个文件系统中,如果不是如何实现复制功能,然后"unlink()"原始文件. (2认同)