7

When moving or copying files as root I often want to set the ownership for those files based on the owner of the directory I am moving the files to.

Before I go off and write a script that parses the rsync output for all the files that were copied over and then goes through those setting chown on each file, is there a better/existing way to do this?

As an example, say I need to copy/move/sync the folder tmp/ftp/new-assests/ to ~user1/tmp/ and to ~user2/html-stuff/ the originals are owned by the user _www and I want the target files and the folder containing them and any other folders to be owned by user1 and user2, respectively and the target directories have existing files in them.

Yes, the users could copy the fils themselves if they had read access to that folder, but that is irrelevant in this case. Let’s assume these are all nologin users and they do not have access to the source file, if that helps.

0

2 Answers 2

5

Using rsync:

rsync -ai --chown=user1 tmp/ftp/new-assests/ ~user1/tmp/

This would copy the directory to the given location and at the same time change the ownership of the files to user1, if permitted.

The general form of the argument to --chown is USER:GROUP, but you may also use just USER to set a particular user as owner, as above, or just :GROUP to set a particular group (the : is not optional if you leave the user ID out).

2
  • This works with newer rsync versions and almost all my machines, but not on my Synology rsync version 3.0.9 (I can work around that, though)
    – lbutlr
    Jun 26, 2020 at 11:04
  • 2
    --chown="user1:$(id -g user1)" if you also want to change the gid to that of the primary group of the user. Jun 26, 2020 at 11:12
5

In zsh, you could always do (as root) something like:

(cd tmp/ftp && tar cf - new-assests/) \
   > >(USERNAME=user1; cd ~user1/tmp && tar xopf -) \
   > >(USERNAME=user2; cd ~user2/html-stuff && tar xopf -)

That makes use of two zsh-specific features:

  • setting $USERNAME changes the shell process EUID, UID, GID, EGID and supplementary gids to that of the user as per the user database (as if the user had logged in with that username). Note that if the user doesn't exist in the database, that will be silently ignored by USERNAME=username, but cd ~username would then fail and cause the subshell to exit.
  • Redirecting a fd several times for output (here stdout, to two different process substitutions) triggers a tee like behaviour to send the output to the two targets (enabled with the mult_ios option, on by default). That saves reading the source twice.

Note that if any of the unpacking tar processes dies, that will likely interrupt the whole pipeline.

ksh or bash don't have that change-user features, but you could use su or sudo instead if available, and tee in place of the multios feature:

(cd tmp/ftp && tar cf - new-assests/) |
  tee >(cd ~user1/tmp && sudo -u user1 tar xopf -) |
  (cd ~user2/html-stuff && sudo -u user2 tar xopf -)

That assumes the target user has write permission to the target directory.

Some tar implementations have a --owner/--group or -chown/-chgrp options to override the user and group names of files stored in an archive. So another option would be to do something like:

(cd tmp/foo && tar --owner=user1 --group="$(id -g user1)" -cf - new-assets) |
  (cd ~user1/tmp && tar xpf -)

And repeat for user2.

In any of those, you may want to consider what to do if the files have ACLs as there's no one size fits all solution there.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .