Filehandles, files, directories
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#
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:
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, $! holds the errno from the
last failing call. A return value less than scalar @files is
the reliable “something went wrong” signal; $! tells you what
the last failure was, not every failure.
Global state it touches#
$!— set to the errno of the last underlyingchown(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 and getgrnam:
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 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 $! set to
EPERM.
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:
chown $uid, $gid, '/var/log/app.log'
or die "chown failed: $!";
Change the group only, leaving the owner alone:
chown -1, $gid, @files;
Translate names to numeric ids before calling:
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:
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:
open my $fh, '>', '/tmp/out' or die $!;
chown $uid, $gid, $fh;
Edge cases#
Empty file list:
chown $uid, $gid;— no files to act on, returns0, does not touch$!.-1in 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. Underuse warningsyou get anArgument isn't numericwarning, 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:
chownfollows symlinks and changes the pointed-to file. To chown the link itself, uselchown(2)viasyscallor 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\*FHor amy $fhto mean “this handle.”Give-away restriction: on POSIX systems with
_PC_CHOWN_RESTRICTEDset for the target path, only root can change the owner at all. Probe with: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— change file permission bits; takes the same “mode, then file list” shape and returns the same number-of-files-changed countstat— read the current owner, group, and mode of a file before deciding what to changeumask— set the default permission mask for files created by this process; complementschownfor newly created filesgetpwnam— translate a user name to the numeric uidchownrequiresgetgrnam— translate a group name to the numeric gidchownrequires$!— holds the errno of the last failing per-filechown(2)when the return count is below the list length