A nice way to find out whether chown actually changes ownership
of files even if they stay the same (e.g. from pduck to pduck)
is to run the command under strace. This way we can see the APIs
that actually get called.
I created a test file which is owned by me and my group.
Then I did chown pduck:pduck test.txt but with strace
prepended:
$ touch test.txt
$ ls -l
total 0
-rw-r--r-- 1 pduck pduck 0 Jun 16 12:10 test.txt
$ strace chown pduck:pduck test.txt
execve("/bin/chown", ["chown", "pduck:pduck", "test.txt"], 0x7ffd0309c990 /* 74 vars */) = 0
brk(NULL) = 0x5589645df000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
...
newfstatat(AT_FDCWD, "test.txt", {st_mode=S_IFREG|0644, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
fchownat(AT_FDCWD, "test.txt", 1000, 1000, 0) = 0
close(1) = 0
close(2) = 0
exit_group(0) = ?
+++ exited with 0 +++
As we can see, the ownership is indeed unconditionally changed from
pduck:pduck to 1000:1000 (which are the numerical IDs of pduck:pduck).
You have multiple options:
chown --from=pduck:pduck pgoose:pgoose text.txt
Will only change the ownership to pgoose:pgoose if it currently is pduck:pduck.
Files with other ownerships remain untouched. Add -R to make the changes
recursively.
find . -type f -user pduck -group pduck -exec chown pgoose:pgoose {} +
This will (recursively) find all files owned by pduck:pduck and only
for them run chown pgoose:pgoose ….
find . -type f -not -\( -user pduck -or -group pduck -\) -exec chown pduck:pduck {} +
Changes ownership of files that do not belong to user pduck or group pduck.
As long as you don't have hundreds of thousands of files I don't think there is
much difference in the performance.
When I do chown -R ... then usually because a whole directory has "wrong" ownership
(for example on thumbdrives). But I usually never do chmod -R because files
and directories need different permissions and the x has a different meaning for them.
We have many questions here on how to fix that terrible chmod -R 777 … thing.
Instead, I do it in two separate commands (find -type d … and find -type f …).