chgrp — quick reference
Basic ownership
Set the group on one or more paths. You need write permission on the file's parent directory (or sudo for files you do not own).
| When to use | Command |
|---|---|
| Change group on one file | chgrp GROUP file |
| Change group on several files at once | chgrp GROUP file1 file2 file3 |
| Change group on a directory entry only (not contents) | chgrp GROUP directory |
| Use numeric GID instead of group name | chgrp 1001 file |
| Copy group from another file | chgrp --reference=refile target |
Recursive and conditional
Walk directory trees or change only when the current group matches.
| When to use | Command |
|---|---|
| Change group on a directory and everything below it | chgrp -R GROUP directory |
| Change only if the current group matches OLD | chgrp --from=OLD GROUP file |
Refuse to recurse on / (safety) |
chgrp -R --preserve-root GROUP /path |
Symbolic links
By default chgrp changes the target file. Use -h to change the symlink inode itself.
| When to use | Command |
|---|---|
| Change group of the file a symlink points to (default) | chgrp GROUP symlink |
| Change group of the symlink itself | chgrp -h GROUP symlinkchgrp --no-dereference GROUP symlink |
Output control
| When to use | Command |
|---|---|
| Print a line for every file processed | chgrp -v GROUP file |
| Print only when the group actually changes | chgrp -c GROUP file |
| Suppress most errors (e.g. missing paths in a batch) | chgrp -f GROUP file |
Help and version
| When to use | Command |
|---|---|
| Show built-in usage | chgrp --help |
| Show implementation version | chgrp -Vchgrp --version |
chgrp — command syntax
Synopsis from chgrp --help on Ubuntu 25.04 (chgrp uutils coreutils 0.2.2):
chgrp [OPTION]... GROUP FILE...
chgrp [OPTION]... --reference=RFILE FILE...
Options:
-c, --changes like verbose but report only when a change is made
-f, --silent / --quiet suppress most error messages
-v, --verbose output a diagnostic for every file processed
--preserve-root fail to operate recursively on '/'
--no-preserve-root do not treat '/' specially (the default)
--reference <RFILE> use RFILE's group rather than specifying GROUP
--from <GROUP> change the group only if its current group matches GROUP
-R, --recursive operate on files and directories recursively
-h, --no-dereference affect symbolic links instead of referenced file
--dereference affect referent of symlink (default)
-H -L -P traverse symlinks to directories (see man page)chgrp updates the group field in the inode. Permission bits from chmod are unchanged; only the group owner changes.
chgrp — command examples
Essential Change group on one file and verify
Use this when a shared file landed with the wrong group after a copy or unpack.
Run the command:
sudo groupadd cschgrp_demo
echo 'shared data' > /tmp/chgrp-file.txt
sudo chgrp cschgrp_demo /tmp/chgrp-file.txt
ls -l /tmp/chgrp-file.txtSample output:
-rw-r--r-- 1 root cschgrp_demo 12 ... /tmp/chgrp-file.txtThe group column should show cschgrp_demo. The user owner (here root) stays the same.
Clean up:
rm -f /tmp/chgrp-file.txt
sudo groupdel cschgrp_demoEssential Apply one group to several files
Listing multiple paths in one invocation avoids repeated command lines in scripts.
Run the command:
sudo groupadd cschgrp_demo
echo a > /tmp/f1.txt; echo b > /tmp/f2.txt
sudo chgrp cschgrp_demo /tmp/f1.txt /tmp/f2.txt
ls -l /tmp/f1.txt /tmp/f2.txtSample output:
-rw-r--r-- 1 root cschgrp_demo 2 ... /tmp/f1.txt
-rw-r--r-- 1 root cschgrp_demo 2 ... /tmp/f2.txtrm -f /tmp/f1.txt /tmp/f2.txt
sudo groupdel cschgrp_demoEssential Recursive group change on a directory tree
-R updates the directory itself and every file and subdirectory under it — typical for /var/www or project checkouts.
Run the command:
sudo groupadd cschgrp_demo
mkdir -p /tmp/chgrp-tree/sub
echo nested > /tmp/chgrp-tree/sub/inner.txt
sudo chgrp -R cschgrp_demo /tmp/chgrp-tree
ls -l /tmp/chgrp-tree /tmp/chgrp-tree/sub/inner.txtSample output:
drwxr-xr-x 3 root cschgrp_demo ... /tmp/chgrp-tree
-rw-r--r-- 1 root cschgrp_demo ... /tmp/chgrp-tree/sub/inner.txtWithout -R, only the directory inode changes — files inside keep their old group.
rm -rf /tmp/chgrp-tree
sudo groupdel cschgrp_demoCommon Copy group from a template file (--reference)
Handy when a golden config file already has the right group and you want matching ownership on a new file.
Run the command:
sudo groupadd cschgrp_demo
echo template > /tmp/template.txt
echo app config > /tmp/app.conf
sudo chgrp cschgrp_demo /tmp/template.txt
sudo chgrp --reference=/tmp/template.txt /tmp/app.conf
ls -l /tmp/template.txt /tmp/app.confSample output:
-rw-r--r-- 1 root cschgrp_demo ... /tmp/app.conf
-rw-r--r-- 1 root cschgrp_demo ... /tmp/template.txtrm -f /tmp/template.txt /tmp/app.conf
sudo groupdel cschgrp_demoCommon Set group by numeric GID
Scripts sometimes only know the GID from LDAP or NFS — chgrp 1005 file works when the name is not in /etc/group on this host.
Run the command:
sudo groupadd cschgrp_demo
GID=$(getent group cschgrp_demo | cut -d: -f3)
echo data > /tmp/gid.txt
sudo chgrp "$GID" /tmp/gid.txt
ls -l /tmp/gid.txtSample output:
-rw-r--r-- 1 root cschgrp_demo ... /tmp/gid.txtPrefer group names in hand-run commands for readability.
rm -f /tmp/gid.txt
sudo groupdel cschgrp_demoCommon Symlink: target (default) vs link (-h)
Default behavior changes the referent. -h changes the symlink's own group — rare, but needed on systems that support symlink ownership.
Run the command:
The lab below creates a symlink with ln -sf before testing ownership; see the create symbolic link on Linux for link versus target behavior.
sudo groupadd cschgrp_demo
echo target > /tmp/target.txt
ln -s /tmp/target.txt /tmp/link.txt
sudo chgrp cschgrp_demo /tmp/link.txt
ls -l /tmp/target.txt /tmp/link.txt
sudo chgrp -h cschgrp_demo /tmp/link.txt
ls -l /tmp/link.txtSample output:
lrwxrwxrwx 1 root cschgrp_demo ... /tmp/link.txt -> /tmp/target.txt
-rw-r--r-- 1 root cschgrp_demo ... /tmp/target.txtrm -f /tmp/link.txt /tmp/target.txt
sudo groupdel cschgrp_demoAdvanced Verbose (-v) and changes-only (-c) output
Use -v for audits and -c in cron jobs when you only want lines for files that actually changed.
Run the command:
sudo groupadd cschgrp_demo
echo x > /tmp/v.txt
sudo chgrp -v cschgrp_demo /tmp/v.txt
sudo chgrp -c cschgrp_demo /tmp/v.txtSample output:
changed group of '/tmp/v.txt' from root to cschgrp_demoA second run with -c may print nothing because the group already matches.
rm -f /tmp/v.txt
sudo groupdel cschgrp_demoAdvanced Change group only when --from matches
--from=OLD skips files that are not in group OLD — useful when fixing a batch without clobbering intentional groups.
Run the command:
sudo groupadd cschgrp_demo
echo x > /tmp/from.txt
sudo chgrp --from=root cschgrp_demo /tmp/from.txt
ls -l /tmp/from.txtSample output:
-rw-r--r-- 1 root cschgrp_demo ... /tmp/from.txtIf the file were already cschgrp_demo, uutils exits 0 with no message and leaves the group unchanged — unlike GNU chgrp, there is no error when --from does not match.
rm -f /tmp/from.txt
sudo groupdel cschgrp_demochgrp — when to use / when not
| Use chgrp when | Use something else when |
|---|---|
|
|
chgrp vs chown
| chgrp | chown | |
|---|---|---|
| Changes | Group only | User and/or group |
| Typical syntax | chgrp group file |
chown user:group file |
| When | Shared trees, web content | Full ownership transfer |
chown user:group file can set both in one step; use chgrp when the user owner is already correct.
Related commands
Permission and ownership workflow on Linux.
| Command | One line |
|---|---|
| chgrp | Change group owner (this page) |
Browse the full index in our Linux commands reference.
chgrp — interview corner
What does chgrp do?
chgrp changes the group owner of files and directories. The user owner and permission bits stay the same. Every file has a user, a group, and mode bits — chgrp only edits the group field in the inode.
You need permission on the file (or sudo) and the target group must exist (or be a valid GID).
A strong answer is:
"chgrp sets the group owner without touching the user owner — I use it for shared project dirs and fixing group after tar extracts."
What is the difference between chgrp and chown?
chgrp changes only the group. chown can change the user, the group, or both (chown user:group file).
Pick chgrp when the user is correct and only the group is wrong.
A strong answer is:
"chgrp is group-only; chown handles user and group. I use chgrp when I must not alter the user owner."
What does chgrp -R do?
-R / --recursive walks a directory tree and applies the new group to every file and subdirectory under the path, including the directory itself.
Without -R, only the single directory entry changes — contents keep their old group. Use --preserve-root if you want recursion to fail when the path is /.
A strong answer is:
"-R applies the group to the whole tree. I verify path twice before recursive chgrp on production data."
Does chgrp follow symbolic links?
By default, chgrp changes the target file the symlink points to. -h / --no-dereference changes the symlink inode itself (where the OS supports it).
That matches the default for most file operations — dereference unless you opt out.
A strong answer is:
"Default is dereference — group change hits the target. -h changes the symlink itself when needed."
When do you need sudo for chgrp?
When you are not the file owner and lack CAP_FOWNER, or when assigning a group you cannot chgrp to as a normal user. On shared admin paths (/etc, /var/www) sudo is routine.
As owner you can usually chgrp to a group you belong to.
A strong answer is:
"sudo when I don't own the file or I'm setting a group the current user can't assign — typical on system and web roots."
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
invalid group |
Group name not in /etc/group |
sudo groupadd name or use numeric GID |
Operation not permitted |
Not owner and not root | sudo chgrp ... |
cannot access 'file': No such file |
Wrong path | Check path; use -f to batch past missing files |
| Directory fixed, files inside not | Forgot -R |
chgrp -R GROUP dir |
| Symlink changed wrong inode | Default dereference | Use -h to affect the link |
--from appears to do nothing |
Current group does not match (uutils exits 0) | Check stat -c %G file; match --from to current group |
-f still exits 1 on missing file |
uutils suppresses stderr only | Ignore exit in scripts or test path first |
| Behavior differs on Ubuntu 25.04 | uutils coreutils vs GNU | Compare chgrp --version; syntax matches this page for uutils 0.2.2 |
