Linux Ownership Command Generator
Build a chown or chgrp command that does exactly what you mean. Name the user and
group, point it at one directory or twenty, and decide whether it should walk the whole tree
(-R), what it should do with symlinks, and whether it is allowed to touch files that
already belong to somebody else. Every flag is explained in plain English, the checks below catch the
chown -R mistakes that actually take servers down — the root of the filesystem, a relative path you
thought was absolute, a system directory, root-owned files left in a home directory — and the
--from form gives you a one-command undo. Paste a line of ls -l output and the tool reads
the current owner and group out of it for you. Nothing is uploaded, and no command is ever run here: you copy
it, read it, and decide.
100% private — nothing is uploaded or stored. The paths, user names and groups you type are used only by the JavaScript in this tab to assemble the command. No filenames, accounts or commands are sent to this website or anywhere else, nothing is logged, and the generated command is never executed for you — there is no server side, no shell and no SSH connection involved.
Quick starts
1. What should the ownership become?
2. Which files and directories?
3. How careful should it be?
Generated command
ReadyChecks on this command
What each part does
| Part | Plain English |
|---|
Read the current owner out of ls -l
Paste a line of ls -l output and the current owner and group are read out of it and dropped into
the --from field, which turns the generated command into a change that can only touch files with
that owner — and gives you an undo.
A loaded file is read with the browser’s FileReader and never leaves your device. To get a clean listing to paste, run ls -l /var/www/html or stat -c '%U:%G %n' /var/www/html.
How it works
Linux stores an owner and a group for every file as two numbers in the inode: the user ID (UID) and the
group ID (GID). The text you type — www-data:www-data — is a name that
chown looks up in /etc/passwd and /etc/group on the machine that runs
the command, then writes the matching number. That is why the same command can work on one server and fail
with chown: invalid user: 'www-data' on another: the account simply does not exist there. The
numeric form (33:33) skips the lookup, which is why containers usually use it.
The owner:group argument is four different commands depending on how you punctuate it.
chown alice changes the owner and leaves the group alone. chown alice: also sets the
group to alice’s login group. chown :staff changes only the group, exactly like
chgrp staff. chown alice:staff sets both. A colon with nothing after it is not
decoration — dropping it is the single most common reason a “fixed” ownership is still
wrong afterwards.
Recursion is where the damage happens. Without -R only the paths you named change, so a directory
can end up owned by www-data while every file inside it still belongs to root.
With -R the whole tree changes — including things you may not have thought about, which is
why GNU chown refuses to run recursively on / unless you disable
--preserve-root, and why --from exists: it narrows the change to the entries that
currently match, so the command cannot claim a file that belongs to a real user.
Ownership is not permission. chown rewrites the UID and GID; the rwx bits, the
set-user-ID and set-group-ID bits, ACLs and extended attributes are not touched — although most
filesystems do clear the set-uid and set-gid bits when the owner changes, because leaving them set would let
the old owner keep a privilege they had. If the goal is “this account should be able to write here”,
ownership is usually the right tool; if the goal is “this file must be readable by everyone”, you
want chmod.
chown argument forms
| Argument | What changes | When to use it |
|---|---|---|
| user | Owner only. The group is left exactly as it is. | You only care who owns it. |
| user:group | Owner and group together. | The normal case: a web root or a home directory. |
| user: | Owner, and the group becomes that user’s login group. | Debian/Ubuntu and Raspberry Pi OS, where the group matches the user name. |
| :group | Group only — identical to chgrp group. | Shared project directories. |
| user.group | An old compatibility spelling of user:group. | Avoid it: a dot is legal in a user name, so the interpretation is ambiguous. |
| 1000:1000 | Numeric UID and GID, no name lookup. | Containers, chroots and cross-distro scripts. |
| --reference=FILE | Copy the owner and group of another path onto the targets. | “Make this match that, whatever it is.” |
| --from=OLD | Not a target owner — a filter: only entries currently owned by OLD are changed. | Repairing a tree without claiming files that belong to other accounts. |
Users and groups you will meet
These are the usual suspects on a Debian or Ubuntu box, Raspberry Pi OS or a container. The numbers are the
convention, not a guarantee — always confirm on the machine itself with getent passwd www-data or
id -u www-data, because a numeric owner that is right on one host can point at a different person
on another.
| Name | Typical UID / GID | What it is for |
|---|---|---|
| root | 0 / 0 | The superuser. Files here are effectively untouchable by normal accounts. |
| www-data | 33 / 33 | The Debian and Ubuntu web server account (Apache and nginx both use it). RHEL-family systems use apache or nginx instead. |
| nobody / nogroup | 65534 / 65534 | The unprivileged account that daemons and Samba drop to. Debian spells the group nogroup; RHEL uses nobody. |
| pi | 1000 / 1000 | The default Raspberry Pi OS user (newer images ask you to pick a name, but it still gets UID 1000). |
| ubuntu | 1000 / 1000 | The default cloud-image user on Ubuntu Server. |
| daemon, bin, sys, systemd-* | 1–999 | System accounts. Changing their files’ ownership is how a service stops starting. |
Recipes that solve a real problem
| Situation | Command |
|---|---|
| Uploads fail after a deploy to a Debian/Ubuntu web root. | sudo chown -R www-data:www-data /var/www/html — and check the app’s own user is in the www-data group if both need to write. |
sudo was used to create files in your home directory, and now your editor and SSH refuse to use them. | sudo chown -R "$USER": ~/.ssh ~/.gnupg — the trailing colon resets the group to your login group. |
| A USB stick on a Raspberry Pi shows up owned by root. | sudo chown -R pi:pi /media/pi/USBNAME. If it is exFAT or NTFS, ownership cannot be stored at all — set uid=1000,gid=1000 in the mount options instead. |
| A tree is a mix of root-owned and correctly-owned files after an rsync run as root. | sudo chown -R --from=root:root www-data:www-data /var/www/html — only the root-owned entries change. |
| A shared project folder needs a group that can write, without making everything world-writable. | sudo chown -R root:developers /srv/project then sudo chmod -R g+rwX /srv/project and set the setgid bit on directories with chmod g+s. |
| A container running as UID 1000 cannot write to a bind mount. | sudo chown -R 1000:1000 ./data — matching the container’s user by number avoids depending on names that do not exist in the image. |
| You want to make a new file match an existing, correctly-configured one. | sudo chown --reference=/etc/nginx/nginx.conf /etc/nginx/sites-available/mysite |
When chown does not work
chown: changing ownership of '…': Operation not permitted
You are not root. Only a process with CAP_CHOWN may give a file to a different user — that is a deliberate restriction, because otherwise anyone could hand you a file with set-uid bits attached. Re-run with sudo. If you are already root, the filesystem is the problem: see the entries below.
chown: invalid user: 'www-data'
The account does not exist on this machine. Check with getent passwd www-data; if it is missing, the package that creates it is not installed (on Debian that is apache2 or nginx-common), or you are inside a container with a minimal base image. Use the numeric UID instead — 33:33 — if you only need the number to be right.
The command succeeds but ls -l still shows the old owner
Either you changed a different path (a trailing slash on a symlink, or a relative path resolved from another directory — pwd -P tells you where you really are), or the mount is not the one you think it is. findmnt -T /path shows which filesystem owns that directory. A bind mount over the directory hides the underlying files: chown the source of the mount, not the mount point.
chown: changing ownership of '…': Read-only file system
The filesystem is mounted read-only, which is normal for a squashfs image, a failing disk remounted by the kernel, or ro in /etc/fstab. Remount it read-write (sudo mount -o remount,rw /mountpoint) only if you are sure the medium is healthy — on an ext4 volume that has gone read-only because of I/O errors, remounting hides a real problem.
Nothing changes on a FAT32, exFAT or NTFS stick
Those filesystems have no UID or GID field per file, so every entry appears to be owned by whoever mounted it. Ownership is decided by the mount options instead: uid=1000,gid=1000,umask=022 for vfat, or the uid/gid options of ntfs-3g. No amount of chown will stick, and it usually fails silently or with “Operation not permitted”.
An NFS or SMB share refuses the change even as root
NFS exports with root_squash (the default) map root to nobody, so root on the client has no privilege on the server. Fix it on the server side, or export with no_root_squash for the specific client if that is genuinely appropriate. On a CIFS/SMB mount the server owns the metadata; noperm or a uid=/gid= mount option is the only lever you have.
One file simply will not change, whatever you do
Check the immutable and append-only attributes: lsattr /path. A file flagged +i cannot be modified or re-owned by anyone, root included, until you clear it with sudo chattr -i /path. Docker images and some package-managed files also land on a read-only overlay layer, where the change needs to happen in a volume or in the image build instead.
Questions
What is the difference between chown and chgrp?
chown changes the owner and, if you give one, the group. chgrp changes only the group and never touches the owner — which is the safe choice when the owner is already correct and you only need a project group to get access.
Does chown -R follow symlinks?
Only the ones it is explicitly told to. By default -R walks the tree without dereferencing symlinks it meets, so the link itself keeps its ownership and the target is not reached through it. -h changes the link itself, -H follows a link named on the command line, and -L follows everything — which can wander into completely different trees, so it is rarely what you want with -R.
Can I undo a chown?
Not automatically: the previous owner is not stored anywhere. Record it first with stat -c '%U:%G %n' /path, or generate the --from form so the undo is the same command with the two names swapped — the downloaded script ends with exactly that line, commented out.
Why does my home directory have root-owned files?
Because something ran under sudo and created them — an editor, pip install --user, a docker command without group membership, or sudo npm install -g. The fix is sudo chown -R "$USER": ~. The permanent fix is to stop running those commands with sudo; ~/.cache and ~/.config are the usual casualties, and the symptom is an application that starts with an “EACCES” or “permission denied” error.
Should the web root be owned by www-data or by my deploy user?
Owned by the deploy user, with the group set to www-data and group read (and write where uploads land): the web server does not need to own the files to read them, and a compromised web process then cannot rewrite your code. The common compromise is sudo chown -R www-data:www-data /var/www/html for simplicity — workable, but it means an upload vulnerability can modify the application itself.
Before you run it
- Run the command on a test path first, or add
-cso only the files that actually change are printed. - If the tree is large, this is not reversible: note the current owner with
stat -c '%U:%G %n' /pathbefore you start. - Pair an ownership fix with the matching
chmodmode — the Chmod Permission Calculator turnsrwxr-xr-xinto the octal mode and back. - Changing ownership of
/etc,/usr,/binor/libwill breaksudo, logins or the package manager. This generator refuses to be quiet about those paths for a reason.
Related tools
Suggested
Luke Keam | techgeek.biz