9

This is my first question although I've been lurking for a while.

Question: I would like to use find to get only the files in a directory with permissions not set to 644 (or another permission value). Is there shorter way to write this or is the only way to just use the -perm and -or options and list each permission type except for 644?

This is part of a larger command that I was hoping to speed up:

find /path/to/dir/ -type f -print0 | xargs -0 chmod 644

I'm hoping that providing xargs only the file names that need updated will speed it up. The directory has ~ a million files but only ~10,000 usually need permissions updated. I think the command is slow because it is still piping all the files regardless. Maybe there is a more efficient approach to the larger command. Let me know if you know of one. I'd still like to know the answer to this question though. And btw, I can't update the permissions before adding the files to the directory.

1
  • The command executes in < 2 seconds when before it took more than 5 minutes so this is a much better method although I never see examples doing it this way. Thanks everyone. find /path/to/dir/ -type f ! -perm 0644 -print0 | xargs -0 chmod 644
    – M Brown
    Jul 30, 2010 at 22:12

4 Answers 4

19

The ! operator returns true when a condition is false.

So while -perm 0644 matches files that have rw-r--r-- permissions set, ! -perm 0644 matches those that don't have those permissions.

The command you need is:

find /path/to/dir/ -type f ! -perm 0644 -print0 | xargs -0 chmod 644
1
  • 2
    This works great. The ! flag was exactly what I needed. The query is now almost instant instead of taking ~ 5 minutes. I now see it mentioned in the man file at the bottom.
    – M Brown
    Jul 30, 2010 at 22:06
3
  find /path/to/dir ! -perm 0644 

And

    find /path/to/dir ! -perm 0644 -exec chmod 0644 {} \;
3
  • /path/to/dir has to be before the !. Jul 30, 2010 at 21:33
  • This works also but for whatever reason -exec is slower than piping to xargs for this since it is a large directory. -exec might be performing individual commands instead of batching like xargs?
    – M Brown
    Jul 30, 2010 at 22:07
  • 2
    @M Brown, in the future, try using + instead of \;. That will do the same kind of batching as xargs. Jul 30, 2010 at 22:19
3

At least with GNU find, you can use the ! operator for negation with -perm. For example:

find /path/to/dir ! -perm 644

Based on the example you're giving, are you just looking to ensure that the owners have at least read/write and everyone has at least read? If so, then you can just do it with chmod:

chmod -R a+r,u+w /path/to/dir/*
1
  • The ! operator is what I was missing. I have to use find and then pipe to xargs because of the large number of files in the directory. chmod can't handle the number of files.
    – M Brown
    Jul 30, 2010 at 22:10
2

One possible solution would be if you have less directories, run a chmod -R 644 /path/to/dir and then run a find /path/to/dir -type d -exec chmod 755 {} \;.

1
  • There are no directories only files. I use xargs because of the large number of files.
    – M Brown
    Jul 30, 2010 at 22:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .