The command to change the group owner on a whole directory is:
chgrp -R newgroup dir_name
For example:
chgrp -R staff .
But when dir_name
contains locked files or directories, this command will fail with:
chgrp -R staff .
chgrp: ./file.txt: Operation not permitted
If you run the command with super user privileges it will fail too:
/usr/bin/sudo chgrp -R staff .
Password:
chgrp: ./file.txt: Operation not permitted
If the number of files locked is small, there is a manual workaround
through the use of the command chflags
.
Check that there is a specific flag (uchg
) associated with a given locked file:
ls -@delO file.txt
-rw-r--r-- 1 bob staff uchg 32 Aug 8 11:38 file.txt
Remove temporarily the uchg
flag:
chflags nouchg file.txt
Change recursively the group:
chgrp -R admin .
Reset the initial uchg
flag:
chflags uchg file.txt
But this method can't adapt to a huge directory structure with hundreds
of locked files. This receipe doesn't scale at all.
What is the basic simple method to change the group owner of a whole directory structure containing locked files, while preserving this locked
status?
The same problem arises with many commands to manage directories containing locked files but I focused here on a practical
and simple case.
Best Answer
The following is an example of how I would workaround the issue by creating a wrapper script for the
chgrp
command to act upon a target directory having issues with locked files.Using a bash script, named
chgrpld
, I'd pass it the same command line arguments (options, operand and directory) I would if executingchgrp
on a directory. Note that my naming convention was simply to add the lettersld
to it representing locked directory, in that it works on directories that are locked, or not, and or containing files/directories that are locked too. So where I'd normally use, e.g.,chgrp -R staff foo
, wherefoo
is a directory, I'd usechgrpld -R staff foo
instead. The script is also coded to work on a directory that is not locked and or does not contain locked filesystem objects as well, thus allow the use ofchgrpld
as a regular replacement forchgrp
when targeting a directory, if I don't want to check for locked filesystem objects first or havechgrp
fail first to then have to usechgrpld
anyway.Note: This script employes a limited amount of error checking, enough to work under limited testing conditions. It is not coded to handle an embedded newline in the name of a filesystem object, which IMO doesn't belong there in the first place! Feel free to modify as needed/wanted to suite your needs, adding additional error checking if/when wanted/needed.
The testing environment was OS X 10.11.5 in a temporary directory, as shown in the listing below, having two directories, each with one file in it and one of the files locked. One directory/file set is in the
admin
group and the other set is in thestaff
group and I'm wanting everything to be in thestaff
group. (See Testing Note at end of answer for additional testing information.)The Terminal output shows:
chgrp
, showing its error output.chgrpld
, executing without error.To create the
chgrpld
bash script and have it available at the command prompt:In Terminal:
touch chgrpld
and press enter.open chgrpld
and press enter.From the Browser:
chgrpld
file and save it, then close the file.Back in Terminal:
chmod +x chgrpld
and press enter.sudo mkdir -p /usr/local/bin
and press enter. Note that on a clean install of OS X 10.11.5, thebin
directory at/usr/local
did not exist even though it's already in thePATH
.sudo cp chgrpld /usr/local/bin
and press enter.chgrpld
should now be available to use, just like thechgrp
command.Source code for
chgrpld
:Synopsis:
chgrpld [−fhv][−R[−H | −L | −P]] group directory
See
man chgrp
in Terminal for description of options andgroup
operand.directory
is the name/pathname of the target directory that is locked, or not, and or containing files/directories that are locked too. Note that unlikechgrp
which allows multiple objects, e.g.group file ...
to act upon,chgrpld
is coded to act upon one target directory, and recursively with the-R
option, at a time.Note: The user invoking chgrpld must belong to the specified group and be the owner of the directory and locked filesystem objects, or be the super-user.
As expected in SIP versions of the OS, this will not work upon SIP protected filesystem objects if SIP is enabled.
The image below shows syntactical highlighting of the code with spaced and indented comments for easier reading to help explain a little about what the code is doing.
Testing Note: Note that even though the testing environment shown above is limited nonetheless I did test it under a more complexed hierarchal directory structure with many more locked nested directories and files, with names containing spaces, and or backslashes within the filename, without issue. Obviously for demonstration purposes, I'm only showing a bare minimum structure for proof of concept. Again, as noted above, "It is not coded to handle an embedded newline in the name of a filesystem object, which IMO doesn't belong there in the first place!".