Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moving a file on Linux in C

Tags:

c

linux

  • Platform: Debian Wheezy 3.2.0-4-686-pae
  • Complier: 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.

like image 856
John Vulconshinz Avatar asked Jul 03 '13 01:07

John Vulconshinz


People also ask

How do I move a file in Linux?

After you have selected each file (Figure 2), you can either right-click one of the selected files and then choose the Move To option, or just drag and drop them into a new location. The selected files (in this case, folders) will each be highlighted. Moving files on the Linux desktop is incredibly easy.

How do I move a file from one directory to another in C?

You can then right-click one of the selected files and select Copy and then open the directory where you want the files to go and do a right-click and select Paste. CTRL+C will copy and CTRL-V will paste.

How do I copy and move files in Linux?

You have to use the cp command. cp is shorthand for copy. The syntax is simple, too. Use cp followed by the file you want to copy and the destination where you want it moved.

Which command is used to move files in Linux?

To move files, use the mv command (man mv), which is similar to the cp command, except that with mv the file is physically moved from one place to another, instead of being duplicated, as with cp.


2 Answers

The usual way to move a file in C is to use rename(2), which sometimes fail.

If you cannot use the rename(2) syscall (e.g. 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); 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). You might also care about copying attributes using getxattr(2), setxattr(2), listxattr(2). You could also in some cases use sendfile(2), as commented by 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). 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. Several libraries provide functions doing that, e.g. 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). 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. You could either study its source code, or use strace(1) to understand what that command does (in terms of syscalls(2)). In some open source Unix shells like sash or busybox, mv might be a shell builtin. See also path_resolution(7) and glob(7).

There are subtle corner cases (imagine another process or pthread doing some file operations on the same filesystem, directory, or files). 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 or newlines, or starts with an initial -. See errno(3).

like image 62
Basile Starynkevitch Avatar answered Oct 19 '22 10:10

Basile Starynkevitch


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)
like image 39
kgraney Avatar answered Oct 19 '22 09:10

kgraney