简体   繁体   English

在 Linux 上用 C 移动文件

[英]Moving a file on Linux in C

  • Platform: Debian Wheezy 3.2.0-4-686-pae平台:Debian Wheezy 3.2.0-4-686-pae
  • Complier: GCC (Debian 4.7.2-5) 4.7.2 (Code::Blocks)编译器:GCC (Debian 4.7.2-5) 4.7.2 (Code::Blocks)

I want to move a file from one location to another.我想将文件从一个位置移动到另一个位置。 Nothing complex like moving to different drives or to different file systems.没有什么比移动到不同的驱动器或不同的文件系统更复杂的了。 I know the "standard" way to do this would be simply copying the file and then removing the original.我知道执行此操作的“标准”方法是简单地复制文件,然后删除原始文件。 But I want some way of preserving the file's ownership, mode, last access/modification, etc. .但我想要某种方式来保留文件的所有权、模式、上次访问/修改等。 I am assuming that I will have to copy the file and then edit the new file's ownership, mode, etc. afterwards but I have no idea how to do this.我假设我必须复制文件,然后编辑新文件的所有权、模式等,但我不知道如何执行此操作。

The usual way to move a file in C is to use rename(2) , which sometimes fail.在 C 中移动文件的常用方法是使用rename(2) ,这有时会失败。

If you cannot use the rename(2) syscall (eg because source and target are on different filesystems), you have to query the size, permission and other metadata of the source file with stat(2) ;如果您不能使用rename(2)系统调用(例如,因为源和目标在不同的文件系统上),则必须使用stat(2)查询源文件的大小、权限和其他元数据; copy the data looping on read(2) , write(2) (using a buffer of several kilobytes), open(2) , close(2) and the metadata using chmod(2) , chown(2) , utime(2) .复制数据循环read(2)write(2) (使用几千字节的缓冲区), open(2)close(2)和元数据使用chmod(2)chown(2)utime(2) . You might also care about copying attributes using getxattr(2) , setxattr(2) , listxattr(2) .您可能还关心使用getxattr(2)setxattr(2)listxattr(2)复制属性。 You could also in some cases use sendfile(2) , as commented by David C. Rankin .在某些情况下,您也可以使用sendfile(2) ,正如David C. Rankin所评论的那样。

And if the source and target are on different filesystems, there is no way to make the move atomic and avoid race conditions (So using rename(2) is preferable when possible, because it is atomic according to its man page).如果源和目标位于不同的文件系统上,则无法使移动原子化并避免竞争条件(因此,最好尽可能使用rename(2) ,因为根据其手册页,它是原子的)。 The source file can always be modified (by another process) during the move operations...在移动操作期间,源文件总是可以被修改(由另一个进程)...

So a practical way to move files is to first try doing a rename(2) , and if that fails with EXDEV (when oldpath and newpath are not on the same mounted filesystem), then you need to copy bytes and metadata.因此,移动文件的一种实用方法是首先尝试执行rename(2) ,如果EXDEV失败(当oldpathnewpath不在同一个挂载的文件系统上时),那么您需要复制字节和元数据。 Several libraries provide functions doing that, eg Qt QFile::rename .一些库提供了这样做的函数,例如 Qt QFile::rename

Read Advanced Linux Programming - and see syscalls(2) - for more (and also try to strace some mv command to understand what it is doing).高级Linux编程-看看系统调用(2) -更多的(并且也尽量strace一些mv命令来了解它在做什么)。 That book is freely and legally downloadable (so you could find several copies on the Web).那本书可以免费且合法地下载(因此您可以在网上找到几本)。

The /bin/mv command (see mv(1) ) is part of GNU coreutils which is free software . /bin/mv命令(参见mv(1) )是GNU coreutils 的一部分,它是自由软件 You could either study its source code, or use strace(1) to understand what that command does (in terms of syscalls(2) ).您可以研究其源代码,也可以使用strace(1)来了解该命令的作用(就syscalls(2) 而言)。 In some open source Unix shells like sash or busybox , mv might be a shell builtin.在一些像sashbusybox这样的开源Unix shell 中mv可能是一个内置的 shell。 See also path_resolution(7) and glob(7) .另请参阅path_resolution(7)glob(7)

There are subtle corner cases (imagine another process or pthread doing some file operations on the same filesystem, directory, or files).有一些微妙的极端情况(想象另一个进程或 pthread 在同一个文件系统、目录或文件上执行一些文件操作)。 Read some operating system textbook for more.阅读一些操作系统教科书以了解更多信息。

Using a mix of snprintf(3) , system(3) , mv(1) could be tricky if the file name contains weird characters such as tab or使用的混合的snprintf(3) ,系统(3) , MV(1)如果该文件名中包含怪异字符,如标签或可能是棘手的 or newlines, or starts with an initial - .或换行符,或以首字母-开头。 See errno(3) .参见errno(3)

If the original and new location for the file are on the same filesystem then a "move" is conceptually identical to a " rename ."如果文件的原始位置和新位置在同一文件系统上,则“移动”在概念上与“ 重命名”相同。

#include <stdio.h>

int rename (const char *oldname, const char *newname)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM