Change a File's Group Safely with chgrp
You have a file the wrong team can read, or a shared directory that needs a different group, and chgrp fixes it in one line. This guide uses GNU chgrp from coreutils 9.4, takes about ten minutes, and shows you where recursion and symbolic links can bite.
The route
Jump straight to the step you need, or tick off Done means at the end.
- You need: a shell, a target path, and membership of the group you want to assign.
- It changes state. Use an ordinary account for files you own where you can, and
sudoonly when the target or group policy demands it.
1. Check the command and your groups
Confirm which executable will run and which groups your account belongs to:
$ command -v chgrp
/usr/bin/chgrp
$ chgrp --version
chgrp (GNU coreutils) 9.4
$ id -Gn
alice users
The version line helps when you compare a script with another host. The manual page installed here is dated August 2026 and describes GNU coreutils 9.4. Group names are host-specific, so replace GROUP_NAME below with a group printed by your own id -Gn, or one your administrator has explicitly granted you.
Checkpoint
You have chosen one test file and one permitted group before running anything that changes ownership.
2. Change one file
The new group goes first and one or more paths follow:
$ chgrp GROUP_NAME /path/to/report.txt
Success is silent. The command changes the group owner, not the file's content or permission bits. In a script, check the exit status as well:
$ printf 'exit status: %s\n' "$?"
exit status: 0
$ stat -c 'group=%G path=%n' /path/to/report.txt
group=GROUP_NAME path=/path/to/report.txt
Check $? straight after chgrp, before the stat, because any intervening command replaces the status.
Tip
If the file belongs to another account, or local policy blocks the change, sudo chgrp ... may be right, but only if you administer that system. Elevation is not a substitute for checking the target path.
3. Show what changed across several files
Use --verbose when you want a line for every path:
$ chgrp --verbose GROUP_NAME /path/to/report.txt /path/to/archive.txt
group of '/path/to/report.txt' changed to GROUP_NAME
group of '/path/to/archive.txt' retained as GROUP_NAME
The exact wording includes your paths and varies with the old group. If you only want output when something changed, use --changes instead:
$ chgrp --changes GROUP_NAME /path/to/report.txt
Both forms leave the files in their new state.
Recovery
To undo a change, run chgrp again with the previous group, which you record beforehand with stat -c '%G' FILE. If you do not know the previous group, stop and recover it from backup or audit data rather than guessing.
4. Copy a group from a reference file
When one file already has the right group, point --reference at it:
$ stat -c 'reference group=%G path=%n' /path/to/good-file
reference group=GROUP_NAME path=/path/to/good-file
$ chgrp --reference=/path/to/good-file /path/to/report.txt
$ stat -c 'group=%G path=%n' /path/to/report.txt
group=GROUP_NAME path=/path/to/report.txt
- The reference is always dereferenced. A reference symlink supplies the group of its target.
- It saves repeating a group name in a script. The catch is that changing or replacing the reference file changes the result.
- Inspect both paths first.
5. Change a directory tree deliberately
Adding --recursive applies the change to the directory and everything below it:
$ chgrp --recursive --verbose GROUP_NAME /path/to/project-data
Warning
This is a broad ownership change. Inspect the path first, and consider a review with find /path/to/project-data -xdev -print if crossing mounted filesystems would be a problem. chgrp has no dry-run option, so a verbose run is not a preview.
By default, recursion does not follow symbolic links. On root protection, --preserve-root prevents recursive operation on /, while --no-preserve-root is the default and adds no such protection. Add --preserve-root to make an accidental root target fail:
$ sudo chgrp --recursive --preserve-root GROUP_NAME /path/to/project-data
Do not use --no-preserve-root in a routine command. The option name is a warning in itself.
Recovery
If recursion changes the wrong tree, stop immediately, record the affected paths from your logs or backup, and restore the intended group explicitly. There is no universal undo command because the original group may differ for every path.
6. Handle symbolic links on purpose
Without recursion, the default is --dereference: the command affects the file the link points to. With --no-dereference, it tries to change the link itself:
$ chgrp --no-dereference GROUP_NAME /path/to/link
$ stat -c 'group=%G type=%F path=%n' /path/to/link
Changing a link's own group only works on systems that support it, and elsewhere the command can fail. For recursive work, the traversal options --H, --L and --P control how links to directories are treated:
--Pis the default. It does not traverse links.- The last one wins. If more than one traversal option appears, only the final one takes effect.
- Pick one explicitly. Keep a single choice in any reviewed script.
7. Diagnose a failed change
Use --verbose to identify the path that failed, then inspect it without changing anything:
$ chgrp --verbose GROUP_NAME /path/to/report.txt
chgrp: changing group of '/path/to/report.txt': Operation not permitted
$ ls -ld /path/to/report.txt
$ namei -l /path/to/report.txt
The usual causes:
- A misspelt group.
- A group that does not exist on this host. Check with
getent group GROUP_NAME. - No search permission on a parent directory.
namei -lshows where. - Not enough authority over the file. Check the path permissions before adding elevation.
Tip
--silent and --quiet suppress most errors, so avoid them while investigating.
Done means
- The group was legitimate. You checked it against
id -Gnor an administrator-approved group. - The change landed.
chgrpreturned status 0 andstatshows the intended group. - Recursion was aimed correctly. It hit the right tree and used
--preserve-rootwhere appropriate. - Link behaviour was a choice. You understood the default traversal rules.
- You can undo it. The previous group is known or recorded.