I had an interesting question today: “What happens if I Ctrl C in the middle of an mv operation? Will the file be corrupted?” Without considering error handling, this question needs to be discussed in separate cases.

• Is it on the same file system?
• Is the object of the mv a file or a folder?

First, the simplest case: mv a file on the same filesystem, where mv is done using rename syscall.

 1 2 3 4 5 6  execve("/usr/bin/mv", ["mv", "a", "b"], 0x7ffe6ae9f580 /* 51 vars */) = 0 ... renameat2(AT_FDCWD, "a", AT_FDCWD, "b", RENAME_NOREPLACE) = 0 ... exit_group(0) = ? +++ exited with 0 +++ 

By POSIX definition, the rename operation is atomic, and subsequent additions of renameat and renameat2 to the Linux kernel also meet this requirement. This is made clear in rename(2).

  1 2 3 4 5 6 7 8 9 10 11 12 13  rename() renames a file, moving it between directories if required. Any other hard links to the file (as created using link(2)) are unaffected. Open file descriptors for oldpath are also unaffected. If newpath already exists, it will be atomically replaced, so that there is no point at which another process attempting to access newpath will find it missing. However, there will probably be a window in which both oldpath and newpath refer to the file being renamed. If newpath exists but the operation fails for some reason, rename() guarantees to leave an instance of newpath in place. 

You can also use rename to mv a folder on the same filesystem, so I won’t go into that again.

In summary, mv operations on the same filesystem are always atomic, and there is no chance of being interrupted by Ctrl-C, which is often referred to as uninterruptable.

Next, we deal with the case of not being on the same file system. For Linux, not being on the same filesystem is actually more strictly limited to not being under the same mount point. That is, rename syscall will return an EXDEV error regardless of whether they are on the same filesystem at the bottom, as long as they have different mount points.

 1 2 3 4 5  EXDEV oldpath and newpath are not on the same mounted filesystem. (Linux permits a filesystem to be mounted at multiple points, but rename() does not work across different mount points, even if the same filesystem is mounted on both.) 

It would obviously be very uncomfortable for mv, which is exposed for user use, to not support moving around the filesystem, and these considerations are documented in mv.

  1 2 3 4 5 6 7 8 9 10 11 12 13 14  The rename() function is able to move directories within the same file system. Some historical versions of mv have been able to move directories, but not to a different file system. The standard developers considered that this was an annoying inconsistency, so this volume of POSIX.1‐2017 requires directories to be able to be moved even across file systems. There is no -R option to confirm that moving a directory is actually intended, since such an option was not required for moving directories in historical practice. Requiring the application to specify it sometimes, depending on the destination, seemed just as inconsistent. The semantics of the rename() function were preserved as much as possible. For example, mv is not permitted to rename'' files to or from directories, even though they might be empty and removable. 

Specifically, mv is implemented by degenerating to copy & unlink to move across filesystems, as we can confirm by reading the source code and analyzing strace. archlinux uses coreutils, so take a brief look at it.

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24  static bool do_move (char const *source, char const *dest, const struct cp_options *x) { bool copy_into_self; bool rename_succeeded; bool ok = copy (source, dest, false, x, ©_into_self, &rename_succeeded); if (ok) { ... if (dir_to_remove != NULL) { ... status = rm ((void*) dir, &rm_options); assert (VALID_STATUS (status)); if (status == RM_ERROR) ok = false; } } return ok; } 

So if you call Ctrl C while mving a file across filesystems, mv may leave an incomplete file at src or dst. But mv will always make sure that one of src or dst is complete, not that both src and dst are incomplete. As mentioned in the manual page.

 1 2 3 4 5 6  If the copying or removal of source_file is prematurely terminated by a signal or error, mv may leave a partial copy of source_file at the source or destination. The mv utility shall not modify both source_file and the destination path simultaneously; termination at any point shall leave either source_file or the destination path complete. 

The same guarantee mentioned above applies to mv folders across file systems. src/dst always has a complete file in one place, and mv will always make sure that all files are copied before it starts deleting them.

In general, Ctrl C will not destroy files during mv, and in the most extreme cases, only dst will be copied incompletely or src will be deleted incompletely.