Subject: bug#30477: [PATCH] chmod chown chgrp: added --exclude-files and --exclude-directories

From: Ian Morris Nieves <[email-masked]>
Date: Fri, 16 Feb 2018 22:26:43 -0500

Hi Assaf,

Thanks for taking the time to write this Friday.  I will try to give an explanation, and please forgive that I may be incorrect in some reasoning.  I am not actually an advanced user.  I hope this is not too much text.  If you want the tl;dr summary, the next 1, 2, or 3 paragraphs should work ;)

The concrete scenario is when an entry or mid level user is trying to set filesystem permissions.  In that case, they lack strong experience with pipe/filter concepts, as well as xargs and find (which is a beast in itself).  Googling around can show you that most users are Googling around and copy/pasting commands to set filesystem permissions.  The commands that need to be pulled together to achieve the same outcome as my proposed additions are beyond many.  These new command line arguments achieve similar results but at a much lower experience level. 

The case for usability of filesystem permissions can not be understated because this is the backbone of Linux security, and its usability should not itself be an advanced concept if we expect Linux to be used securely.  I have seen many users resort to ugo+rwx permissions to solve “permission denied” errors, and this is frightening.  In most cases I would surmise that the user simply needed -R —exclude-files +rx   And in none of these cases do the users understand find or xargs or |, etc. beyond their understanding of copy/paste.

I do believe that usability was a goal of {chown, chmod, chgrp} because they were given -R and users were not forced to use find $DIR | xargs chmod [NEWMODE].  However, -R alone probably does more harm than good, because it doesn’t differentiate between (at least) directories and files.  Yes advanced users may be using it properly with +X, but +X is itself a pretty poorly understood feature, and its documentation reads like a total hack/afterthought.  My command line options help the user be significantly more correct, and probably require little/no cleanup afterwards.  In that sense, these proposed additions increase the ability to more properly use -R while maintaining backwards compatibility.

Here is a basic but common use case illustrated.  Suppose you have a directory/file structure:

d_1
	nf_1
	nf_2
	xf_1
	d_2
		…

(Where d=directory, nf=normal file, xf=executable file)
Then you could use the following commands:

chmod -R —exclude-files ug=rwx,o=rx d_1
chmod -R —exclude-directories ug=rw,o= d_1
chmod ug+x d_1/xf_1

This is a straightforward pattern and what it is doing is explicit to all.  Requiring find, |, xargs, etc not only breaks the idiom, it takes the the idiom out of the hands of all but the advanced users.

On the subject of find:

Yes, find is powerful, and can differentiate between symlinks, sockets, and more.  I did not add —exclude-symlinks because ultimately in most cases these resolve to simply another directory or file, which the current proposed additions address.  I did not address sockets because they are so rare they are easy to set the permissions for non-recursively in one/few single command(s).  So I have not overlooked those in terms of my design decisions on the proposed extensions.  -print0 is not necessary (to the best of my knowledge) unless you are using find | xargs …..

Even though find exists, and can be combined with {chown, chmod, chgrp}, it is not part of coreutils and the latter should not be overly dependent on other commands outside coreutils for basic and intended functionality, especially if said functionality is low hanging fruit.  I think that this line of reasoning has precedent in that fact that -R is included in {chown, chgrp, chmod}.  -R was trivial to implement (in my opinion after having studied the sourcecode of these commands) and it could have been left out, so all users would be required to learn find, but that is not the case, -R was included.  For the same reasons -R was included, I hope to make a case for enabling -R to differentiate between directories and files.

In the end, yes, find is awesome.  But why should {chown, chgrp, chmod} require find to be actually useful?  Note, I am not making a slippery slope argument that would justify adding massive complexity for only a small benefit.  I am making an argument about usability to justify adding almost 0 complexity to get a massive benefit.  So I do believe I am respecting Linux philosophy ;)  If these proposed additions do not make sense, why did -R ever make sense?

Background of the situation:

I spent the last 10 days dealing with file permissions bugs and flaws found in docker dockerfiles which are used to essentially create filesystem images.  I went through lots and lots of {chmod, chown, chgrp}, and I was shocked at how quickly find had to be used to do something so basic as differentiate between files and directories, and how useless -R actually was.  I think that the majority of new users to Linux are actually going to be software engineers who are using it as a layer in a software stack and not as an OS per se.  That is to say, they are not advanced Linux users, they are entry/mid level.  I say that to make a reasonable argument that there are increasingly many smart and talented users of Linux that are entry/mid level, and would greatly benefit from such proposed functionality.

Cheers,
Ian

> On Feb 16, 2018, at 5:16 PM, Assaf Gordon <[email-masked]> wrote:
> 
> Hello Ian,
> 
> On Thu, Feb 15, 2018 at 07:44:39PM -0500, Ian Morris Nieves wrote:
>> Attached please find a new feature I created to simplify setting permissions (especially recursively), which enables the user to separately target files or directories.
> 
> Can you provide a concrete example/scenario where this is needed,
> and find/xargs are not sufficient ?
> 
> For example, to apply chmod/chown/chgrp on files alone
> (like your --exclude-directories), one can use:
> 
>  find $DIR -type f | xargs chmod [NEWMODE]
> 
> And of course, find's predicates can be expanded to include
> symlinks, sockets and other conditions, and using -print0 for
> safer execution.
> 
> regards,
> - assaf