recursively change file permission but not directories?
Solution 1
The better solution should be
chmod -R ug=rwX,o=rX /path
where the capital X
means: set execute bit if
the file is a directory or already has execute permission for some user
(quoted from chmod
man page).
Or also, if you want to use find
find /path \( -type f -exec chmod ug=rw,o=r {} + \) -o \
\( -type d -exec chmod ug=rwx,o=rx {} + \)
Solution 2
Using find is the 'right' way, and the only programmatic way, although there are variations:
find . -type f -exec chmod ug+rw {} + # "+" may not be on all systems
or
find . -type f -print0 | xargs -r0 chmod ug+rw # similar to the -exec + functionality
or the slowest:
find . -type f -exec chmod ug+rw {} \; # in case xargs is not installed
Each of these selects a file (not directory, not symlink) and applies the chmod
command on it. The first two reduce the number of calls to chmod
by appending the file to the end of an internal command line each time until a maximum is reached (often 10), then calls the command and starts rebuilding a new command. The last statement spawns a new process for each file, so it is less efficient.
Related videos on Youtube
user394
Updated on September 18, 2022Comments
-
user394 over 1 year
I was doing a mass recursive change of permissions of some files that I had migrated to a unix system. I changed them to ug+rw, but then I found that I could not traverse subdirectories. I looked at the man page for
chmod
and didn't see any explanation for excluding directories, so I googled a little and found that people usedfind
to recursively change the permissions on directories to 'execute' for user and group. I did that and then I could look into them.But it seemed to me that I should be able to be able to do this find
chmod
-- to recursively change the files to read/write but not make the directories untraversable. Have I done this the 'right' way or is there a simpler way to do it? -
The Dude over 9 yearsI used the wide open for everyone version of this command for my USB hard drive: chmod -v -R ugo=rwX /path Thanks!
-
Wildcard over 8 yearsEvidently there is no way without using
find
to set all file permissions to 600 and all directory permissions to 700. (I arrived here through my googlings on the subject.) If that can be done with a singlechmod -R
command, feel free to correct me. -
enzotib over 8 years@Wildcard: not exactly, the command
chmod -R u=rwX,go= /path
does almost what you want: it sets all dirs to 700 and all files to 600 or 700, depending on if the execution bit is already set or not, and I think this is the right thing to do. -
Wildcard over 8 years@enzotib, yes—almost, but not quite. In my case I want to disable the execution bit for all files (but not directories of course) regardless of whether they are scripts or binaries or whatever. So the
find
command you wrote was very helpful as a template. :) -
Michael about 8 years@Wildcard what about removing the execute bit first, recursively, then add it back only to directories using the above command?
-
Wildcard about 8 years@Michael, that would be fairly error-prone as once the execute bit is removed on a directory, you can't access any of the files inside. So you'd have to ensure you were doing a strictly depth-first search and only removing the execute bit at the deepest level. Not sure how to do that with
find
; the answer given here is simpler. -
Admin almost 2 yearsPOSIX requires
find
to support-exec
...{} +
; see pubs.opengroup.org/onlinepubs/009695399/utilities/find.html . On the other hand, it doesn't requirefind
to support-print0
, norxargs
to support-0
.