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

Ready

Checks on this command

What each part does

PartPlain 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.

or

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

ArgumentWhat changesWhen to use it
userOwner only. The group is left exactly as it is.You only care who owns it.
user:groupOwner 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.
:groupGroup only — identical to chgrp group.Shared project directories.
user.groupAn old compatibility spelling of user:group.Avoid it: a dot is legal in a user name, so the interpretation is ambiguous.
1000:1000Numeric UID and GID, no name lookup.Containers, chroots and cross-distro scripts.
--reference=FILECopy the owner and group of another path onto the targets.“Make this match that, whatever it is.”
--from=OLDNot 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.

NameTypical UID / GIDWhat it is for
root0 / 0The superuser. Files here are effectively untouchable by normal accounts.
www-data33 / 33The Debian and Ubuntu web server account (Apache and nginx both use it). RHEL-family systems use apache or nginx instead.
nobody / nogroup65534 / 65534The unprivileged account that daemons and Samba drop to. Debian spells the group nogroup; RHEL uses nobody.
pi1000 / 1000The default Raspberry Pi OS user (newer images ask you to pick a name, but it still gets UID 1000).
ubuntu1000 / 1000The default cloud-image user on Ubuntu Server.
daemon, bin, sys, systemd-*1–999System accounts. Changing their files’ ownership is how a service stops starting.

Recipes that solve a real problem

SituationCommand
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 -c so 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' /path before you start.
  • Pair an ownership fix with the matching chmod mode — the Chmod Permission Calculator turns rwxr-xr-x into the octal mode and back.
  • Changing ownership of /etc, /usr, /bin or /lib will break sudo, logins or the package manager. This generator refuses to be quiet about those paths for a reason.

Luke Keam
Spot a bug or want a custom utility built? I'd love to hear from you. Get in touch
Luke Keam | techgeek.biz