find . .[^.]* -type f -print0 | xargs -0 sudo chmod 664; does not work
Solution 1
find
will not skip dot files, so .[^.]*
(.[!.]*
in standard syntax) is redundant and will cause those files to be processed twice (and directories to be descended twice). (also note that .[!.]*
misses files called ..foo
for instance).
However, find
by default, does not descend into symlinks to directories. So if media
is a symlink to an area outside .
, files in there will not be processed.
You can use -L
to tell find to follow symlinks. Note however that it will also cause chmod
to be called for files that are symlinks to regular files.
sudo find -L . -type f -exec chmod 664 {} +
Or with some find
/xargs
implementations:
find -L . -type f -print0 | sudo xargs -r0 chmod 664
Contrary to what has been said here, xargs
and find -exec +
will take care of splitting the list of arguments to chmod
if it's too big.
However it should be noted that the limit we're talking about here is the cumulative size of the arguments and environment passed to a command (to the execve(2)
system call).
find
and xargs
will make sure that that limit is not reached (and leave a little margin), but if you run it as:
find . -type f -print0 | xargs -r0 sudo chmod 644
instead of:
find . -type f -print0 | sudo xargs -r0 chmod 644
The sudo
command (called by xargs
) will receive all the arguments to pass to chmod
and will also pass a SUDO_COMMAND
environment variable to chmod
that contains the list of files another time, so it will about double the size of arg+env passed to chmod
and would explain why the limit is exceeded.
Solution 2
It is possible that the argument string you are passing to chmod
is too long. You have a few options here.
Using find's exec option
When used with a semicolon, find's exec option will run a command once per file it finds: find . .[^.]* -type f -exec sudo chmod 664 -- '{}' \;
.
Limiting the number of arguments with xargs
xargs -n5
will pass a maximum of five arguments per command instance. You could also use the -s
flag to limit the number of characters passed to the command: xargs -s4096
. You can increase the limits for better performance; just be careful not to go to high.
Recursive chmod
chmod
has a recursive option. This will affect directories as well as files though. If you are concerned about unsetting the execution bits on directories, you can run chmod -R +X
(note the uppercase X
) after you run your first command to recursively set the execution bits of your directories.
Related videos on Youtube
Comments
-
clime over 1 year
I am using this command to set permissions for files recursively
clime@vm6879 /srv/www-php/steeltrading $ find . .[^.]* -type f -print0 | xargs -0 sudo chmod 664
But after executing that command permissions of some files (most of them) are still not changed.
clime@vm6879 /srv/www-php/steeltrading $ ll media/xmlconnect/system/ok.gif -rwxrwxr-x. 1 www www 295 Jul 5 2012 media/xmlconnect/system/ok.gif
If I run just
find
to look if the file is in the list, I can see it:clime@vm6879 /srv/www-php/steeltrading $ find . .[^.]* -type f | grep ok.gif ./media/xmlconnect/custom/ok.gif ./media/xmlconnect/original/ok.gif ./media/xmlconnect/system/ok.gif
If I move into directory media a run the command again, the file finally gets the right permissions.
clime@vm6879 /srv/www-php/steeltrading $ cd media/ clime@vm6879 /srv/www-php/steeltrading/media $ find . .[^.]* -type f -print0 | xargs -0 sudo chmod 664 clime@vm6879 /srv/www-php/steeltrading/media $ ll xmlconnect/system/ok.gif -rw-rw-r--. 1 www www 295 Jul 5 2012 xmlconnect/system/ok.gif
It looks like
sudo chmod 664
is not performed for some files and it seems thatxargs
is the problem but It is strange (no error messages). Any idea what might be the cause, please?EDIT: Or maybe piping lots of data might be a problem?
-
Admin about 11 yearsTry using
find
's-exec
option:find . .[^.]* -type f -exec sudo chmod 664 -- '{}' \;
. -
Admin about 11 yearsYou might be passing too many arguments to
chmod
. Tryxargs -n5
to only allow 5 arguments per command. -
clime about 11 years
-n5
worked for my original command! And with -n100 it still works and is also fast. Thank you! If you could make that an answer... -
Gilles 'SO- stop being evil' about 11 yearsWhat is
ll
an alias for? does it includels -L
by any chance?
-
-
clime about 11 yearsYou are right about that
.[^.]*
being redundant but there is not a symlink on the path to to that file. As I pointed out the file is being found by find and adding -n5 solved that problem. Also I didn't mention that but even files in the current directory were untouched. I am sure that the command was exiting prematurely. If I try to run the same command with the same data on another system, I getsudo: unable to execute /bin/chmod: Argument list too long
Strangely I did not get this error on the system in question. -
Stéphane Chazelas about 11 years@clime, yes, see how that error is reported by
sudo
and not byfind
. See the update to my answer. -
Gilles 'SO- stop being evil' about 11 years
xargs
takes care of not passing a too long argument string. On the face of the question (which I'm betting is incomplete: there's probably a symlink involved somewhere) none of what you propose would make a difference. -
alordiel about 11 yearsAt least I was close. In the future, I will do more research before posting answers.