I have to find in a folder the files not having certain permissions (755). The sub-directory has other sub-directories containing in total millions of files, and the find ./ -not -perm 755 command it just takes too long.

Is there a more efficient / faster command to do this task ( like ls combined with grep or so ) ?

  • 2
    As a side note, 755 is an odd set of permissions for millions of files, are you sure 644 wouldn't be a better choice? – EightBitTony Apr 12 '16 at 14:08
  • Why do you need to find these files? If you're just changing the permissions to match, just chmod -R - see my answer. If you know that the non-executable files are only present at a particular depth in the filesystem, you may be able to guide find with -mindepth and/or -maxdepth - again, give us more context to create a better answer! – Toby Speight Apr 12 '16 at 16:07
  • chmod -R u+rwX,go+rX ./ will recursively ADD rw (owner) or r (group,other) perms on all files and directories, and the x permission for owner,group, and other on all directories (if you want it to set it to exactly rX or rwX, use = rather than +). Note the capital X rather than lowercase x in the chmod command - that sets the execute bit on directories but not other kinds of files. – cas Apr 12 '16 at 23:47
  • @cas - +X will also add the corresponding execute permission to any file that has any one of the three execute bits already set. – Toby Speight Apr 13 '16 at 7:56
  • Another clarification on the question - is this a one-off operation, or do you need to update new files as they are added? If the latter, you may benefit from inotify or similar interface, to only examine files as they are created or changed. – Toby Speight Apr 13 '16 at 7:58

If you use ls -lR you have to then exclude content from the output, somehow, and then grep out what you want.

find is probably quicker. Here's a very quick hack on my machine (the grep's are ugly, I take no pride in them).

tony@trinity:~$ time ls -lR | grep "tony tony" | grep -vc "rwxr-xr-x"

real    0m3.247s
user    0m1.456s
sys     0m1.808s
tony@trinity:~$ time find ./ -not -perm 755 | wc -l

real    0m0.503s
user    0m0.120s
sys     0m0.380s
tony@trinity:~$ time ls -lR | grep "tony tony" | grep -vc "rwxr-xr-x"

real    0m3.128s
user    0m1.564s
sys     0m1.920s
tony@trinity:~$ time find ./ -not -perm 755 | wc -l

real    0m0.501s
user    0m0.196s
sys     0m0.428s

Some notes:

  • I ran both commands twice to remove the chance of difference from caching
  • You'll note they return different counts, my quick hack grep isn't good enough to isolate only the relevant files and directory entries.
  • The point of this is not to show you a better solution, but to show that find is pretty quick compared to raw ls + grep.

There may be faster solutions, such as something in perl, or a way of making ls run faster (setting $LANG? - my tests just showed this knocks a second off the ls output, you can probably tell ls not to sort as well, which might help).

Edit: I've just seen your comment where you also say you need to then change the permissions. In which case, find is absolutely the right answer, because it can do all the work in one go.

find ./ -not -perm 755 -exec chmod 755 {} \;

You should be extremely careful when running that command to make sure you are in the correct location. A safer option would be,

find /actual/full/path -not -perm 755 -exec chmod 755 {} \;

so you avoid changing every file on the system if you're in the wrong place.

Also, you should probably consider softlinks, directories, and non-regular files and modify your find as a result. So, assuming you only care about files, I would start with,

find /actual/full/path -type f -not -perm 755 -exec chmod 755 {} \;

Lastly, you might want to ask yourself if you're changing the permissions of every file in a directory or set of directories which don't have permissions 755 to 755, then you don't need to do anything complex.

find /actual/full/path -type f -exec chmod 755 {} \;

That will just set them all to 755. It might be a little bit quicker (less logic in choosing which files to update vs. updating millions of files worth of permissions, depends I guess on the number of files which are correct already).

  • Thanks, this helped me getting the answer, which is "no faster way" :) I have actually 113+ million files and the number is changing (sometimes dropping, but growing mostly). Running a simple recursive chmod for the folder takes a lot of time as well. I will try to use a different approach. – mazs Apr 12 '16 at 14:19
  • You will not find a faster approach. No matter what you try, it takes a certain minimum amount of time (which varies according to your disk(s), CPU, available RAM and many other factors) to examine every subdirectory and file and it also takes time to change the perms on every subdir and file. – cas Apr 12 '16 at 23:50

If your intent is to make all the files and directories have 755 permissions, you could simply perform a recursive chmod:

chmod -R 755 $directory

If you need files to be mode 644, you might be better with

chmod -R u=rwX,go=rw $directory

This will use a single process to find the necessary files and update their permissions where necessary.

If you need to find files with different permissions for some other reason, then find will be your best choice.

  • As there are 113+ million files, this operation takes 2+ hours and consumes a lot of resources, I can't afford that. Same with find. – mazs Apr 13 '16 at 7:20
  • 100 million directory entries processed in under 10 thousand seconds isn't too bad - you're unlikely to do much better by any means. – Toby Speight Apr 13 '16 at 7:54

If you have mlocate installed it makes this easier, but only if you know part of the file name. Also, unless you make permission changes to the mlocate.db file it requires root.

When installed a cron job should run periodically to update the mlocate database, or you can run updatedb to do it manually. Once there use the command locate .

  • 3
    locate only finds files by name, the query is about finding files based on their permissions? – EightBitTony Apr 12 '16 at 13:22
  • 1
    yup i have to find the files which are not 755 and change them to 755 – mazs Apr 12 '16 at 13:29
  • Apologies, misunderstood the question. Coffee cup is still full. There doesn't appear to be a way to get octal permissions out of ls, you have to stat the file for that. You would need to do a recursive long list and then grep for the permissions you wanted. Throw the -v switch to give you the items that don't match (ls -laR | grep "rwxr-xr-x" -v) – pacmanwa Apr 12 '16 at 13:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.