Ubuntu – Intelligent chmod -x for all executable files that actually cannot be executed


Shot in the sky: do you have a script that does chmod -x on all executable files in the system that actually cannot be executed (i.e., they mistakenly have x flag)?

After copying backup files from NTFS into ext4, the files became executable (html, md, txt, etc.).
I'd like to make the files non-executable, but only those that are really non-executable.
I will likely have to write the script that iterates over all files in the system (smth like for f in ``find /path``; do intelligent_chmod -x $f; done;, where intelligent_chmod has to look into file and identify if it is either ELF or has the first line !#..., etc.)

Best Answer

This uses uses find to look for regular files that have the executable bit set. It then tests them with the file command to see if they really are executables or not. If not, we run chmod a-x on them:

find . -type f -executable \( -exec sh -c 'file -b "$1" | grep -q executable' Test {} \; -o -exec chmod a-x {} \; \)

As you can see, this find command has two -exec expressions which are connected with a logical-OR operator.

How it works

  • -type f -executable

    This tells find to look only for regular files that have the executable bit set.

  • \(

    This begins a group.

    By default, find conditions are AND-ed together and AND binds tighter than OR. In this case, we want to bind just the following two -exec commands together with an OR. To do that, we need a group.

  • -exec sh -c 'file -b "$1" | grep -q executable' Test {} \;

    This has the file program examine each file and grep checks to see if the string executable was in the output of file command.

    In the above, Test serves as the program name ($0) for the sh -c script. (For a discussion of $0 and sh -c, see this question.)

    Here is some sample output from the file command:

    $ file -b bash
    ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=0e188133c8cc5187e22eabd27cbcf46f32060fe3, stripped        
    $ file -b which
    POSIX shell script, ASCII text executable

    As you can see, file is smart enough to identify as executable not just ELF files but also a wide variety of script files.

  • -o

    This is logical-OR. This means that the command which follows will only be executed if file did not identify the file as an executable.

  • -exec chmod a-x {} \;

    This removes the executable bit.

  • \)

    This tells find that we have reached the end of the grouped commands.


As described in man magic, the program file works by examining the strings in a file. Many files have very distinctive strings. An ELF executable, for example, begins with the hex characters 7f 45 4c 46. Jpeg and png graphics have similarly distinct markers. file does not completely parse or analyze a file and, consequently, for some files, however, the magic fails. As Ayrat points out in the comments, file misinterprets the following:

$ cat tmp.py
Now is the time for all good men
to come to the aid of the party.
from xxx import yyy
$ file tmp.py
tmp.py: Python script, ASCII text executable