cp, mv, ownership and attributes

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.

Leave a Reply

Your email address will not be published. Required fields are marked *