kmail.at
contact

elsewhere

EnglishEN
← learning

linux · difficulty ◆◆

chown — reclaim files from the wrong owner

Point chown at a file and say who owns it — the fix for permissions that came out wrong

That file says root owns it, but the process that needs it runs as you — and here comes the one command that settles it.

AI-generated draft · reviewed and editedThis text was generated with AI as a first draft, then reviewed and edited by the author, who holds editorial responsibility for it.

2026-09-22 · 5 min read

$ chown

What chown does

chown (change owner) rewrites the user and/or group fields on a file or directory's inode. Syntax is always owner, then an optional :group: `chown alice file`, `chown alice:dev file`, or `chown :dev file` to touch only the group. It is a chmod cousin with different powers: chmod deals in r/w/x bits, chown decides WHO those bits belong to. You need it the moment a service runs as its own user (nginx, postgres, www-data) but a file got dropped there by root.

One big catch: owner changes need root

A normal user can never hand a file to someone else — that would let you trivially steal every other account's files. Changing the owner needs privilege (Linux: the CAP_CHOWN capability), so that half of chown is root-only, and running it without privileges gives you `chown: changing ownership of 'file': Operation not permitted`, which I watched happen live on this box. The group half is deliberately laxer: the owner of a file may change its group to any group of which that owner is a member, with no sudo at all — `chown :ollama own.txt` succeeded here as a plain user while `chown mail own.txt` did not. That is not a bug, it is the kernel guarding the ownership metadata.

Recursion and references

-R walks a whole directory tree so `chown -R www-data:www-data /var/www` fixes every file and subdirectory in one pass — the standard repair after an extraction or a botched deploy. --reference copies the exact owner:group from a known-good file instead of you typing them. And chown accepts plain names or numeric uid:gid, so scripts can target specific IDs like UID 1000 — though a bare number is still resolved as a user name first and only then as an ID, which is why the manual recommends `+1000:+1000` when you mean the integer and want the database lookup skipped.

Example

$ $ chown alice ./config.ini
$ ls -l --no-group config.ini
$ chown alice ./config.ini
$ ls -l --no-group config.ini
-rw-r--r-- 1 alice 4096 Sep 22 09:12 config.ini

Root hands a single file over to alice. Only the owner changes; the group field is untouched. This is the one-two punch after a deploy drops a config with the wrong owner.

$ $ sudo chown www-data:www-data /var/www/app
$ sudo chown -R www-data:www-data /var/www/app/storage
$ sudo chown www-data:www-data /var/www/app
$ sudo chown -R www-data:www-data /var/www/app/storage
$ ls -l /var/www/app/storage
-rw-r--r-- 1 www-data www-data 12804 Sep 22 09:15 cache.bin
-rw-rw---- 1 www-data www-data 5120  Sep 22 09:15 sessions.db
-rw-r--r-- 1 www-data www-data 880   Sep 22 09:15 log.html

The classic web-tool chain: first fix the top, then -R descends and rewrites every file and subdir so the app's own user can read, write, and clean up its state. Run this after any unzip -q as root.

$ $ sudo chown 1000:1000 data/file.bin
$ stat -c '%A %U:%G %n' data/file.bin
$ sudo chown 1000:1000 data/file.bin
$ stat -c '%A %U:%G %n' data/file.bin
-rw-r--r-- kmail:kmail data/file.bin

Numeric uid:gid form. A bare number is tried as a user name first and only then as an ID — GNU's `+1000:+1000` is the spelling that forces the integer and skips the /etc/passwd lookup entirely. It works even when no account matches, because the kernel only stores the number. UID 1000 is usually the first real user on a fresh box.

$ $ sudo chown --reference=template.config newdir/config.ini
$ stat -c '%U:%G %n' newdir/config.ini template.config
$ sudo chown --reference=template.config newdir/config.ini
$ stat -c '%U:%G %n' newdir/config.ini template.config
kmail:kmail newdir/config.ini
kmail:kmail template.config

--reference copies the owner:group of a known-good file instead of you typing them — handy when you forget which combo the rest of the tree uses.

$ $ chown mail ./own.txt
$ ls -l --no-group own.txt
$ chown mail ./own.txt
chown: changing ownership of './own.txt': Operation not permitted
$ ls -l --no-group own.txt
-rw-rw-r-- 1 kmail kmail 5 Sep 22 09:03 own.txt

Verified live on this box as an unprivileged user: handing your file to another owner — here the user 'mail' — is denied with Operation not permitted, and the file is untouched. That is the root-only half of chown. The group half is not: `chown :group file` succeeds whenever you own the file and belong to the group.

Common flags

chown OWNER:GROUP FILE
The full form. Set both owner and group at once. Omit the colon+group to change only the owner.
-R / --recursive
Walk a directory tree and apply the change to every file and subdir. The -R you'll actually use.
--reference=FILE
Copy the owner:group from another file instead of spelling them out. Great when you forget the exact combo.
:GROUP (leading colon)
Change only the group: `chown :dev file`. Owner stays put — a one-word way to widen team access.
-h / --no-dereference
Change a symlink's ownership instead of following it to the target file it points at.
-v / --verbose
-v / --verbose: print a line for every file processed, changed or not, which is why it gets noisy under -R. Use -c (--changes) instead when you only want the files whose ownership actually moved.
--from=OLD-OWNER
Change ownership only when the file currently matches OLD-OWNER, in the same OWNER:GROUP form. The safety valve when repairing a whole tree, because the gap between find listing a file and chown touching it leaves room for something else to change in between — the manual's own example is `chown -h -R --from=OLDUSER NEWUSER /`.
+UID:+GID (forced numeric)
A leading '+' forces the operand to be read as a number and never as a name, skipping the user and group database lookup: `chown +1000:+1000 file`. The manual documents the same syntax for chgrp, chroot and id, and notes it is not supported on Solaris 10.

History

Born with Unix's user model

chown goes back to the First Edition at Bell Labs, dated 3 November 1971, alongside chmod and the notion that every file carries a user ID and group ID; chgrp came later, in 1975. The idea — files belonging to people, not just sitting in a namespace — is one of the oldest and most copied parts of Unix, and chown is the command that edits ownership where chmod edits permission bits.

The 'only root' rule is a security backstop

Early Unix realized that if any user could give their files to another user, there'd be no way to keep accounts apart. So chown became root-only, and that restriction survived decades precisely because removing it would let a normal user fabricate ownership and, in some cases, gain other users' privileges. The 'Operation not permitted' error you hit is that decades-old guard still standing.

Fun facts

Pros & cons

pros

  • + Fixes 'permission denied' root causes by reassigning who owns a file
  • + Powerful with -R for repairing whole directory trees after deploys and extractions
  • + Accepts names or numeric uid:gid, plus --reference for copying known-good ownership

cons

  • − Mostly root-only: you cannot hand a file to another user without sudo or root, though the owner of a file may still move it into a group they belong to
  • − An -R error can cascade: a wrong path rewrites everything under it, often irreversibly
  • − Symlinks confuse it (you usually want -h), and it's easy to forget the :group vs bare owner form

Takeaways

  1. 1chown OWNER:GROUP FILE sets both at once; `chown :GROUP file` changes only the group.
  2. 2Changing an owner needs root or sudo — an unprivileged user gets 'Operation not permitted'; changing the group of your own file to a group you are in does not.
  3. 3Repair a botched deploy with `sudo chown -R $USER:$USER .` right after extraction.
  4. 4Prefer the numeric uid:gid form in scripts; it skips name lookup and works mid-migration.
  5. 5Use -h to change a symlink's own ownership instead of following it, and --reference to copy known-good values.

Related commands