6

I just copied all the files/subdirectories in my home directory to another user's home directory.

Then I did a recursive chown on his home directory, so that he became the owner of all his files/subdirectories.

The last thing I need to do is a recursive chgrp on his home directory, so that his username will be the group for all his files/subdirectories, instead of my username.

The issue is that there are a couple of subdirectories whose group is "docker". Inside these subdirectories, there are some files/directories whose group is my username, and some other files/directories whose group is "docker".

How do I recursively run chgrp on his home directory so that every single file/subdirectory whose group is my username gets changed to his username, but every single file/subdirectory whose group is "docker" stays "docker"?

pacoverflow
  • 278
  • 3
  • 15

2 Answers2

17

Use find to exclude anything owned by group docker; starting from the target home directory:

find . ! -group docker -exec chgrp newgroup {} +

replacing newgroup as appropriate.

Alternatively, look for anything owned by your group:

find . -group oldgroup -exec chgrp newgroup {} +

replacing oldgroup and newgroup as appropriate.

Stephen Kitt
  • 411,918
  • 54
  • 1,065
  • 1,164
  • 6
    +1 Personally, I prefer the alternate. Specify the exact group you want to search for and replace it with the other. – Jim L. Sep 29 '21 at 20:50
  • @JimL. Yeah, I used the alternate in case there was another group that I didn't see that should stay the same. – pacoverflow Sep 29 '21 at 23:06
6

How do I recursively run (…) so that every single file/subdirectory whose (…) is (…)

The generic answer to this is either find or zsh globs. Use one of these to enumerate the files you want to affect, and the chgrp you already know to act on those files (not in recursive mode, since find or zsh took care of the recursion).

find /home/new-user/some-files -group pacoverflow -exec chgrp new-user {} +

Or, if you're using zsh:

chgrp new-user /home/new-user/some-files/**/*(g:pacoverflow:)

The zsh solution may run into a command line length limit, in which case you can use zargs (similar to xargs or to find's -exec … {} +)

autoload zargs
zargs -- /home/new-user/some-files/**/*(g:pacoverflow:) -- chgrp new-user

or the zsh loadable built-in for chgrp

zmodload -m -F zsh/files b:zf_\*
zf_chgrp new-user /home/new-user/some-files/**/*(g:pacoverflow:)
Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
  • `zf_chgrp` also has the advantage of avoiding a separate process for `chgrp`, which does little more than wrap a system call. – chepner Sep 30 '21 at 13:55