I had always been under the impressions that when moving a file from one Linux filesystem to another (i.e. a new inode is created), that mv
is essentially a cp
command followed by an rm
command.
That’s not quite correct. It is essentially a cp --archive
command followed by an rm
command.
The difference between moving a file and copying a file
Moving a file preserves the ownership and existing file attributes, including the SELinux file type context. In the example case below, you can see that moving a file keeps the owner (chris
) and the SELinux context of the directory in which the file was created (user_home_t
).
A copied file inherits the properties, including the SELinux type context, of its parent directory.
Here’s a demonstration of the difference:
Create and move a file
$ touch test
$ ls -lZ test
-rw-r-----. chris chris unconfined_u:object_r:user_home_t:s0 test
$ sudo mv test /usr/local/bin/
$ ls -lZ /usr/local/bin/test
-rw-r-----. chris chris unconfined_u:object_r:user_home_t:s0 /usr/local/bin/test
$ sudo rm /usr/local/bin/test
Create and copy a file
$ touch test
$ ls -lZ test
-rw-r-----. chris chris unconfined_u:object_r:user_home_t:s0 test
$ sudo cp test /usr/local/bin/
$ ls -lZ /usr/local/bin/test
-rw-r-----. root root unconfined_u:object_r:bin_t:s0 /usr/local/bin/test
The copy of the file has a new owner, and a new SELinux context. Note there is an option (mv -Z
) to reset the SELinux context when moving a file, but it would still maintain the original owner/group.
What does the documentation say?
man cp
and man mv
both directed me to the coreutils documentation for the complete manual. Some of the more relevant excerpts I have included below:
It first uses some of the same code that’s used by ‘cp -a’ to copy the requested directories and files, then (assuming the copy succeeded) it removes the originals.
(From info coreutils 'mv invocation'
)
‘mv’ always tries to copy extended attributes (xattr), which may include SELinux context, ACLs or Capabilities. Upon failure all but ‘Operation not supported’ warnings are output.
(From info coreutils 'mv invocation'
)
So what is cp -a
?
‘-a’
‘–archive’
Preserve as much as possible of the structure and attributes of the original files in the copy (but do not attempt to preserve internal directory structure; i.e., ‘ls -U’ may list the entries in a copied directory in a different order). Try to preserve SELinux security context and extended attributes (xattr), but ignore any failure to do that and print no corresponding diagnostic. Equivalent to ‘-dR –preserve=all’ with the reduced diagnostics.
(From info coreutils 'cp invocation'
)
Which leads us to --preserve=all
:
‘-p’
”–preserve'[=ATTRIBUTE_LIST]’
Preserve the specified attributes of the original files. If specified, the ATTRIBUTE_LIST must be a comma-separated list of one or more of the following strings:
(From info coreutils 'cp invocation'
)
Those attributes include, among others, ownership
, context
(SELinux context), and all
.
Summary
A mv
command, across filesystems, is still essentially a cp
command followed by an rm
command, but with --archive
flag specified for the cp
command. If you encounter unexpected problems after moving a file, double-check the file’s ownership, attributes, and SELinux context.