I'm trying to cleanup permissions on an Apache web server. I'm finding lots of files with the execute bit that don't customarily have it (or should not have it):

$ sudo find /var/www/html -executable -type f | grep '.png'

How can I set the execute bit for regular files that customarily have it (like programs, PHP pages and Bash scripts); and remove it from regular files that customarily don't have it (like TXT, PNG, JPG and ZIP files)?

I feel like find with an -exec and chmod should come into play somewhere. I also expect the selection mechanism will take into account shebangs and other magic headers; and not just rely on an [potentially incorrect] execute bit or a [potentially missing] extension. But my searching is not landing on the right answer. Cf., How can I find only the executable files under a certain directory in Linux? and Find executable files recursively.

  • 1
    Are you searching for something like find /var/www/html -name '*.php' -exec chmod 755 {} \; ? And then find /var/www/html -name '*.png' -exec chmod 644 {} \;'
    – grochmal
    Jul 3, 2016 at 1:59
  • @grochmal - Not really (though I thought about it). I have to do that for every filetype; and it may break if an extension is not quite correct. I'm trying to use find's predicates to select the proper files. I also expect the selection mechanism will take into account shebangs and other magic headers (and not just rely on an extension).
    – user56041
    Jul 3, 2016 at 2:08
  • 2
    There is no bullet proof way to know what files on a webserver should be executable and which shouldn't. One try that i would do: is that all files starting with #! shall be executables and all others shouldn't. That is untrue if you have binary CGIs, but, i guess, almost no one has such dinosaurs anymore.
    – grochmal
    Jul 3, 2016 at 2:09
  • 2
    @grochmal Binary CGIs still have their uses. An example that comes to mind is nut-cgi, a program that queries the status of an UPS and shows the results it in a web page. Jul 3, 2016 at 5:13
  • @SatoKatsura Fair enough, it was my lack of knowledge on useful binary CGIs :)
    – grochmal
    Jul 3, 2016 at 12:42

2 Answers 2


This will go through your files and set the executable bit according to whether file believes that the file should be executable:

find /var/www/html -type f -exec bash -c 'if file -b "$1" | grep -q executable; then chmod +x "$1"; else chmod -x "$1"; fi' None {} \;

The find command is very similar to yours. The change is the addition of the bash commands. It may be simpler to understand them if they are spread out over multiple lines like this:

if file -b "$1" | grep -q executable
    chmod +x "$1"
    chmod -x "$1"

You may, of course, modify the chmod argument to meet your specific needs.

  • This looks good. Its surely much better than what I have now, which is a bunch of data files indicating they are meant to be read as code. Let me test it and report back.
    – user56041
    Jul 3, 2016 at 12:26
  • As I understand speaking of executable bit means for all three "groups"(user, group and other)? This is what chmod +x does.
    – Timo
    Dec 20, 2020 at 12:32
  • 1
    @Timo chmod +x sets all three bits to executable except for the ones that are set in your umask. If you want to override umask and set all three bits, then use chmod a+x where a indicates 'all'. For more details, see man umask. To find out what your current umask is, run the command umask from your shell. If your shell is bash, then you can find more information on umask in man bash.
    – John1024
    Dec 21, 2020 at 1:24

I don't now what is your use case, but I rarely have executable files under my web folder. And on production machines I also remove write permission to most of the files.

For spacial cases i keep a separate file which include all the specific cases, like which folders need writing permission or a different owner, And use it to overwrite the defaults.

find /path/to/webroot/ -type f -exec chmod 644 -c '{}' \;
find /path/to/webroot/ -type d -exec chmod 755 -c '{}' \;
# change owner 
chmod root:www-data /path/to/webroot/ -R

bash .fix-perm

where .fix-perm is just a script file

chmod g+w cache -R
chmod g+w logs -R
  • 1
    "I don't now what is your use case, but I rarely have executable files under my web folder..." - my use case is free software that's running fast and loose.
    – user56041
    Jul 3, 2016 at 12:24

You must log in to answer this question.