--- name: chown signature: 'chown LIST' since: 5.0 status: documented categories: ["Filehandles, files, directories"] --- ```{index} single: chown; Perl built-in ``` *[Filehandles, files, directories](../perlfunc-by-category)* # chown Change the owner and group of a list of files. `chown` takes a numeric user id, a numeric group id, and a list of files, and reassigns ownership on every file that the calling process is allowed to touch. The first two elements of `LIST` are the new `UID` and `GID`, in that order; every element after that is a filename (or, on systems that support `fchown(2)`, a filehandle). A value of `-1` in either of the id slots means "leave that id unchanged" — useful when you want to change only the group, or only the owner. ## Synopsis ```perl chown UID, GID, LIST chown $uid, $gid, $file chown $uid, $gid, @files chown -1, $gid, @files # change group only ``` ## What you get back The number of files whose ownership was successfully changed, as a plain integer. Not a boolean — a call over ten files that succeeds on seven returns `7`. Check against the list length when you need all-or-nothing semantics: ```perl my @files = ('a', 'b', 'c'); my $ok = chown $uid, $gid, @files; $ok == @files or die "chown failed on ", scalar(@files) - $ok, " files: $!"; ``` When any individual file fails, [`$!`](../perlvar) holds the errno from the **last** failing call. A return value less than `scalar @files` is the reliable "something went wrong" signal; [`$!`](../perlvar) tells you what the last failure was, not every failure. ## Global state it touches - [`$!`](../perlvar) — set to the errno of the last underlying `chown(2)` call that failed. Unchanged when every file succeeds. ## Numeric ids only `chown` does **not** accept user or group names. Pass the string `"root"` where a uid is expected and you get a numeric conversion of `0` (with an `Argument … isn't numeric` warning under `use warnings`) — almost never what you want. Translate names to numbers with [`getpwnam`](getpwnam) and [`getgrnam`](getgrnam): ```perl my $uid = getpwnam('alice') // die "no such user"; my $gid = getgrnam('staff') // die "no such group"; chown $uid, $gid, @files; ``` The list-context return of [`getpwnam`](getpwnam) gives the full passwd entry; in scalar context it gives just the uid, which is usually what `chown` wants. ## Permission rules On Linux and every other POSIX system, only the superuser can give a file away to a different owner. An unprivileged user can change the **group** of a file they own, but only to one of their own secondary groups. Trying to do more returns failure with [`$!`](../perlvar) set to `EPERM`. ```perl chown 0, 0, 'passwd.new' or warn "need root to chown: $!"; ``` The restriction is kernel-enforced, not Perl-enforced — there is no pre-check that would save you a failed system call. Rely on the return value. ## Examples Change both owner and group on a single file: ```perl chown $uid, $gid, '/var/log/app.log' or die "chown failed: $!"; ``` Change the group only, leaving the owner alone: ```perl chown -1, $gid, @files; ``` Translate names to numeric ids before calling: ```perl my ($login, $pass, $uid, $gid) = getpwnam('www-data') or die "www-data not in passwd file"; chown $uid, $gid, glob('/var/www/*'); ``` Count how many files were actually reassigned: ```perl my @targets = glob('/srv/data/*.dat'); my $changed = chown $uid, $gid, @targets; warn "only $changed of ", scalar(@targets), " files changed: $!" if $changed != @targets; ``` Chown by filehandle on a system that supports `fchown(2)`. The filehandle must be a glob or a glob reference — a bareword is treated as a filename: ```perl open my $fh, '>', '/tmp/out' or die $!; chown $uid, $gid, $fh; ``` ## Edge cases - **Empty file list**: `chown $uid, $gid;` — no files to act on, returns `0`, does not touch [`$!`](../perlvar). - **`-1` in id position**: standard POSIX sentinel meaning "leave this id unchanged." Works on every supported platform. - **String id**: a non-numeric string silently becomes `0` (root / wheel) after the usual numeric conversion. Under `use warnings` you get an `Argument isn't numeric` warning, but there is no hard error. Always pass an integer. - **Non-existent file**: counted as a failure, does not abort the call. Remaining files still get processed. - **Symlink target**: `chown` follows symlinks and changes the pointed-to file. To chown the link itself, use `lchown(2)` via [`syscall`](syscall) or a module that exposes it — core Perl does not. - **Filehandle form**: on systems without `fchown(2)` (rare in practice on Linux), passing a filehandle raises an exception. Barewords in the file list are always treated as filenames — use `\*FH` or a `my $fh` to mean "this handle." - **Give-away restriction**: on POSIX systems with `_PC_CHOWN_RESTRICTED` set for the target path, only root can change the owner at all. Probe with: ```perl use POSIX qw(pathconf _PC_CHOWN_RESTRICTED); my $restricted = pathconf($path, _PC_CHOWN_RESTRICTED); ``` ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`chmod`](chmod) — change file permission bits; takes the same "mode, then file list" shape and returns the same number-of-files-changed count - [`stat`](stat) — read the current owner, group, and mode of a file before deciding what to change - [`umask`](umask) — set the default permission mask for files created by this process; complements `chown` for newly created files - [`getpwnam`](getpwnam) — translate a user name to the numeric uid `chown` requires - [`getgrnam`](getgrnam) — translate a group name to the numeric gid `chown` requires - [`$!`](../perlvar) — holds the errno of the last failing per-file `chown(2)` when the return count is below the list length