What type of parameter/flag can I use with the Unix find
command so that I search executables?

- 97,681
- 90
- 411
- 885

- 11,810
- 19
- 52
- 70
-
type 'man find'. I think '-executable' is the option you want. – sje397 Dec 16 '10 at 06:44
-
6`find -executable` ... but this does not guarantee that every file listed would actually execute – William Dec 16 '10 at 06:45
-
1Not all implementations of `find` are created equal. The option recommended by @sje397 and @William may not be available. It's better to use the [accepted solution](http://stackoverflow.com/a/4458361/543738) shown below. – Mr. Lance E Sloan Oct 25 '13 at 18:10
-
Also relevant: [How to find the executable files under a certain directory in linux?](http://superuser.com/questions/38981/how-to-find-the-executable-files-under-a-certain-directory-in-linux) – Slothworks Aug 14 '15 at 06:11
-
1Me dislikes all proposals shown below which are based on file permissions. Argumentation: for my GNU operating system (Ubuntu) it is possible to set "x" (executable) flag for for instance ASCII text file. No mimics prevented this operation from successful completion. It needs just small mistake/bug for multiple non-intentioned files to get x flag assigned. Therefore gniourf_gniourf' solutions is my personal favorite. It has however that drawback that for cross-compiled executables needs an emulator or target device. – Nov 13 '17 at 12:23
-
@William True this only finds files that have executable permission bit set. To actually determine if some file is an executable, regardless of any permissions it might have or not have, regardless if it's a shebang shell script or compiled binary, try the `file` command i.e. `file $FILEPATH | grep -q executable` which will return true if `$FILEPATH` appears to be an executable. Neat little command although Im not sure how common it is (comes pre-installed on macOS). Make sure your `file` command is [up to date](http://ftp.astron.com/pub/file/) so that it'll properly detect most shebangs. – tmillr Nov 25 '22 at 01:44
10 Answers
On GNU versions of find you can use -executable
:
find . -type f -executable -print
For BSD versions of find, you can use -perm
with +
and an octal mask:
find . -type f -perm +111 -print
In this context "+" means "any of these bits are set" and 111 is the execute bits.
Note that this is not identical to the -executable
predicate in GNU find. In particular, -executable
tests that the file can be executed by the current user, while -perm +111
just tests if any execute permissions are set.
Older versions of GNU find also support the -perm +111
syntax, but as of 4.5.12 this syntax is no longer supported. Instead, you can use -perm /111
to get this behavior.

- 137,896
- 35
- 246
- 299
-
2
-
1@sourcejedi Thanks. I was actually only talking about non-GNU versions of find (BSD, in particular) but older versions of GNU find actually did support that syntax too. In newer versions you'll have to use `/` instead of `+`. See the updated answer for more details. – Laurence Gonsalves Jul 18 '14 at 22:33
-
Indeed, I misread your answer. Sorry for making it more complicated :). – sourcejedi Jul 19 '14 at 15:30
-
If _symlinks_ to executable files should also be found, include the `-L` option: `find -L ...`. – mklement0 Mar 13 '15 at 19:19
-
It took me a while to understand the implications of "not identical to the -executable predicate" and "just tests if _any_ execute permissions are set": It means that `-perm +111` may yield _false positives_, i.e., files that the current user cannot actually execute. There's no way to emulate `-executable` by testing permissions alone, because what's needed is to _relate_ the _file's_ user and group identity to the _current user's_. – mklement0 Mar 14 '15 at 12:24
-
A POSIX-compliant equivalent of `find . -type f -perm +111 -print` is `find . -type f \( -perm -u=x -o -perm -g=x -o -perm -o=x \)` (sorry for messing that one up in an earlier comment). – mklement0 Mar 14 '15 at 12:26
-
Perhaps a closer approximation of GNU find's `-executable` in BSD find is to use `find . -type f -perm -111` so as to find files that have the executable bit set for ALL security principals (user, group, other) - this strikes me as the typical real-world scenario. (As a bonus, it also happens to be POSIX-compliant, and can also be written as `find . -type f -perm -a=x`.) – mklement0 Mar 14 '15 at 16:45
-
Those finds find files with the execution bit set not executable files. setting the execute bit on a jpeg file does not make it an executable but the above find will show such instances. So if the question is to be intended strictly this answer is technically wrong, if we intend to find files with any of the execute bits set this answer is right. – louigi600 May 13 '16 at 08:31
-
@louigi600 Neither permissions nor `file` are flawless. A file that consists only of "echo hello" will be identified as ASCII text by `file`, but if the execute bit is set it *will* execute. So it isn't a matter of "strictness", but rather which not-entirely-reliable heuristic you want to use. – Laurence Gonsalves May 13 '16 at 22:13
-
@Laurence Gonsalves Ascii text with execution bit set is basically a script with no explicit interpreter. If it contains something your shell understands it will be interpreted. Hello World. this is some thash text with a lucky echo in themiddle of it what now make that executable and although it's ordinary text the middle line will actually do something. So is it text or script ? Sorry the comment don't show new lines ... "echo in themiddle of it" is on a line on it's own. – louigi600 May 16 '16 at 10:18
-
@Laurence Gonsalves yes that's why I use find . -type f -executable -exec file {} \; | grep -wE "executable|shared object|ELF|script|a\.out" to that tou could add "ASCII text" and your issue would be solved and your file will only be found if it has execute permissions. – louigi600 Sep 02 '16 at 09:24
Tip of the hat to @gniourf_gniourf for clearing up a fundamental misconception.
This answer attempts to provide an overview of the existing answers and to discuss their subtleties and relative merits as well as to provide background information, especially with respect to portability.
Finding files that are executable can refer to two distinct use cases:
- user-centric: find files that are executable by the current user.
- file-centric: find files that have (one or more) executable permission bits set.
Note that in either scenario it may make sense to use find -L ...
instead of just find ...
in order to also find symlinks to executables.
Note that the simplest file-centric case - looking for executables with the executable permissions bit set for ALL three security principals (user, group, other) - will typically, but not necessarily yield the same results as the user-centric scenario - and it's important to understand the difference.
User-centric (-executable
)
The accepted answer commendably recommends
-executable
, IF GNUfind
is available.- GNU
find
comes with most Linux distros- By contrast, BSD-based platforms, including macOS, come with BSD find, which is less powerful.
- As the scenario demands,
-executable
matches only files the current user can execute (there are edge cases.[1]).
- GNU
The BSD
find
alternative offered by the accepted answer (-perm +111
) answers a different, file-centric question (as the answer itself states).- Using just
-perm
to answer the user-centric question is impossible, because what is needed is to relate the file's user and group identity to the current user's, whereas-perm
can only test the file's permissions.
Using only POSIXfind
features, the question cannot be answered without involving external utilities. Thus, the best
-perm
can do (by itself) is an approximation of-executable
. Perhaps a closer approximation than-perm +111
is-perm -111
, so as to find files that have the executable bit set for ALL security principals (user, group, other) - this strikes me as the typical real-world scenario. As a bonus, it also happens to be POSIX-compliant (usefind -L
to include symlinks, see farther below for an explanation):find . -type f -perm -111 # or: find . -type f -perm -a=x
- Using just
gniourf_gniourf's answer provides a true, portable equivalent of
-executable
, using-exec test -x {} \;
, albeit at the expense of performance.Combining
-exec test -x {} \;
with-perm +111
(i.e., files with at least one executable bit set) may help performance in thatexec
needn't be invoked for every file (the following uses the POSIX-compliant equivalent of BSD find-perm +111
/ GNU find-perm /111
; see farther below for an explanation):find . -type f \( -perm -u=x -o -perm -g=x -o -perm -o=x \) -exec test -x {} \; -print
File-centric (-perm
)
- To answer file-centric questions, it is sufficient to use the POSIX-compliant
-perm
primary (known as a test in GNU find terminology).-perm
allows you to test for any file permissions, not just executability.- Permissions are specified as either octal or symbolic modes. Octal modes are octal numbers (e.g.,
111
), whereas symbolic modes are strings (e.g.,a=x
). - Symbolic modes identify the security principals as
u
(user),g
(group) ando
(other), ora
to refer to all three. Permissions are expressed asx
for executable, for instance, and assigned to principals using operators=
,+
and-
; for a full discussion, including of octal modes, see the POSIX spec for thechmod
utility. - In the context of
find
:- Prefixing a mode with
-
(e.g.,-ug=x
) means: match files that have all the permissions specified (but matching files may have additional permissions). - Having NO prefix (e.g.
755
) means: match files that have this full, exact set of permissions. - Caveat: Both GNU find and BSD find implement an additional, nonstandard prefix with are-ANY-of-the-specified-permission-bits-set logic, but do so with incompatible syntax:
- BSD find:
+
- GNU find:
/
[2]
- BSD find:
- Therefore, avoid these extensions, if your code must be portable.
- Prefixing a mode with
- The examples below demonstrate portable answers to various file-centric questions.
File-centric command examples
Note:
- The following examples are POSIX-compliant, meaning they should work in any POSIX-compatible implementation, including GNU find and BSD find; specifically, this requires:
- NOT using nonstandard mode prefixes
+
or/
. - Using the POSIX forms of the logical-operator primaries:
!
for NOT (GNU find and BSD find also allow-not
); note that\!
is used in the examples so as to protect!
from shell history expansions-a
for AND (GNU find and BSD find also allow-and
)-o
for OR (GNU find and BSD find also allow-or
)
- NOT using nonstandard mode prefixes
- The examples use symbolic modes, because they're easier to read and remember.
- With mode prefix
-
, the=
and+
operators can be used interchangeably (e.g.,-u=x
is equivalent to-u+x
- unless you apply-x
later, but there's no point in doing that). - Use
,
to join partial modes; AND logic is implied; e.g.,-u=x,g=x
means that both the user and the group executable bit must be set. - Modes cannot themselves express negative matching in the sense of "match only if this bit is NOT set"; you must use a separate
-perm
expression with the NOT primary,!
.
- With mode prefix
- Note that find's primaries (such as
-print
, or-perm
; also known as actions and tests in GNU find) are implicitly joined with-a
(logical AND), and that-o
and possibly parentheses (escaped as\(
and\)
for the shell) are needed to implement OR logic. find -L ...
instead of justfind ...
is used in order to also match symlinks to executables-L
instructs find to evaluate the targets of symlinks instead of the symlinks themselves; therefore, without-L
,-type f
would ignore symlinks altogether.
# Match files that have ALL executable bits set - for ALL 3 security
# principals (u (user), g (group), o (others)) and are therefore executable
# by *anyone*.
# This is the typical case, and applies to executables in _system_ locations
# (e.g., /bin) and user-installed executables in _shared_ locations
# (e.g., /usr/local/bin), for instance.
find -L . -type f -perm -a=x # -a=x is the same as -ugo=x
# The POSIX-compliant equivalent of `-perm +111` from the accepted answer:
# Match files that have ANY executable bit set.
# Note the need to group the permission tests using parentheses.
find -L . -type f \( -perm -u=x -o -perm -g=x -o -perm -o=x \)
# A somewhat contrived example to demonstrate the use of a multi-principial
# mode (comma-separated clauses) and negation:
# Match files that have _both_ the user and group executable bit set, while
# also _not_ having the other executable bit set.
find -L . -type f -perm -u=x,g=x \! -perm -o=x
[1] Description of -executable
from man find
as of GNU find 4.4.2:
Matches files which are executable and directories which are searchable (in a file name resolution sense). This takes into account access control lists and other permissions artefacts which the -perm test ignores. This test makes use of the access(2) system call, and so can be fooled by NFS servers which do UID mapping (or root-squashing), since many systems implement access(2) in the client's kernel and so cannot make use of the UID mapping information held on the server. Because this test is based only on the result of the access(2) system call, there is no guarantee that a file for which this test succeeds can actually be executed.
[2] GNU find versions older than 4.5.12 also allowed prefix +
, but this was first deprecated and eventually removed, because combining +
with symbolic modes yields likely yields unexpected results due to being interpreted as an exact permissions mask. If you (a) run on a version before 4.5.12 and (b) restrict yourself to octal modes only, you could get away with using +
with both GNU find and BSD find, but it's not a good idea.

- 382,024
- 64
- 607
- 775
-
7
-
1@andynormancx :) Well, in terms of sheer number of bullet points, I can offer [this contender](http://stackoverflow.com/a/24276470/45375). – mklement0 Dec 20 '18 at 14:04
So as to have another possibility1 to find the files that are executable by the current user:
find . -type f -exec test -x {} \; -print
(the test command here is the one found in PATH, very likely /usr/bin/test
, not the builtin).
1 Only use this if the -executable
flag of find
is not available! this is subtly different from the -perm +111
solution.

- 44,650
- 9
- 93
- 104
-
Raging downvoters, please leave a note to explain why (you think) my answer is not useful or wrong. – gniourf_gniourf May 05 '14 at 07:12
-
2This works, but it pretty slow. Also, depending on the shell, you might have to wrap or escape the filename place holder, like `'{}'` or `\{\}`. – Ionoclast Brigham Jul 20 '14 at 02:21
-
1@mklement0 this will not find the commands that are executable by me like `-executable` does or like my command does. – gniourf_gniourf Mar 14 '15 at 06:59
-
1Thanks, @gniourf_gniourf - I really had a few misconceptions there. I'm reprinting your other comment here, because I'm at least for now deleting my answer (perhaps to be resurrected, IF there's something salvageable): "`find . -type f -perm -u=x` is _not_ the equivalent of `-executable`: `-executable` matches all files that user can execute, and these include `g+x` if I'm in the proper group or `o+x`. Actually `-perm -u=x` will find lots of files that user can't execute, and miss a few that user can execute." – mklement0 Mar 14 '15 at 11:16
-
1@IonoclastBrigham: While having to quote `{}` is a hypothetical necessity (and quoting doesn't hurt), in practice it's not necessary in POSIX-like shells and `csh`. Do you know shells where it is _is_ required? – mklement0 Mar 14 '15 at 11:58
-
1@gniourf_gniourf: Apart from performance, your solution is equivalent to using GNU find with `-executable`, correct? And, if I now understand correctly, one cannot fully emulate `-executable` by testing permissions alone, because what's needed is to _relate_ the _file's_ user and group identity to the _current user's_, correct? – mklement0 Mar 14 '15 at 12:31
-
1
-
1@mklement0 I use FISH, the Friendly Interactive Shell ("Finally, a command line shell for the 90s..."). It is a POSIX-like shell. But, since orthogonality and ease of use are top goals, they break with the standard whenever they deem it is inconsistent or obtuse. In FISH, '{' and '}' are actually special operators that are used for "brace expansion". The comma-delimited list of strings are each concatenated with whatever strings are adjacent to the open and close braces. Example: `echo Hello{\ World,\ StackOverflow,ooooo\ Nurse}!` prints: `Hello World! Hello StackOverflow! Helloooooo Nurse!`. – Ionoclast Brigham Mar 14 '15 at 19:22
-
4@IonoclastBrigham: Interesting, thanks; so, in `fish`, `{}` must indeed be escaped as either `'{}'` or `\{\}`. Note that `bash`, `ksh`, and `zsh` provide the same kind of brace expansion; however, they print the unquoted token `{}` _as is_ (and thus: no need for escaping), because they do NOT consider it a _valid_ brace expression (they require at least _2_ tokens, or a valid numeric sequence expression), whereas `fish` deems `{}` a _valid_ brace expression that results in the _empty_ string. – mklement0 Mar 14 '15 at 19:37
-
Unfortunately, directories qualify as 'executable' because of their filemode settings, so this command (as well as the 'find' examples given earlier) include directories. Depending on your use case (e.g., try searching for all executables with the name 'java') this may be quite unusable. Not only do you get directories but you also get the title-case version (e.g., Java) as well. – JESii Oct 30 '15 at 16:03
-
@JESii thanks for your comment, but did you overlook the `-type f` predicate? – gniourf_gniourf Oct 30 '15 at 16:18
-
@gniourf_gniourf I might have, but hard to recall at this point. I'll try to retest when I get back to that system. Pretty complicated stuff. – JESii Nov 11 '15 at 12:54
-
1A decent alternative when you need to work on an annoying flavour of Unix, like Solaris... – Eugéne Mar 15 '18 at 13:15
You can use the -executable
test flag:
-executable
Matches files which are executable and directories which are
searchable (in a file name resolution sense).

- 445,704
- 82
- 492
- 529
-
5
-
6Would that be a GNU Find extension? Since the tag is Unix, not Linux, at the least a GNU extension needs to be documented as such. – Jonathan Leffler Dec 16 '10 at 07:46
-
3This option is not supported by the BSD find command found at least on OS X. This is a GNU extension, but might be supported by other flavors of find. – Ionoclast Brigham Oct 24 '12 at 18:00
-
FWIW, I found this to not be on sles 10, but on sles >= 11 (got a little burned by it) – Peter Turner Sep 04 '15 at 19:19
-
Note that this does not actually get all examples. In my case I had a file which I owned as `-rw-r-xr-x` which `-executable` does not detect – Dezza Aug 29 '16 at 15:31
-
@Dezza: That can happen if the file is either owned by you or you're a member of the file's group. In that event the file is _not_ executable _by you_ and therefore `-executable` doesn't report it. – mklement0 Oct 24 '16 at 02:28
find . -executable -type f
does not really guarantee that the file is executable it will find files with the execution bit set. If you do
chmod a+x image.jpg
the above find will think image.jpg is an executable even if it is really a jpeg image with the execution bit set.
I generally work around the issue with this:
find . -type f -executable -exec file {} \; | grep -wE "executable|shared object|ELF|script|a\.out|ASCII text"
If you want the find to actually print dome information about executable files you can do something like this:
find . -type f -executable -printf "%i.%D %s %m %U %G %C@ %p" 2>/dev/null |while read LINE
do
NAME=$(awk '{print $NF}' <<< $LINE)
file -b $NAME |grep -qEw "executable|shared object|ELF|script|a\.out|ASCII text" && echo $LINE
done
In the above example the file's full pathname is in the last field and must reflect where you look for it with awk "NAME=$(awk '{print $NF}' <<< $LINE)" if the file name was elsewhere in the find output string you need to replace "NF" with the correct numerical position. If your separator is not space you also need to tell awk what your separator is.

- 716
- 6
- 16
This worked for me & thought of sharing...
find ./ -type f -name "*" -not -name "*.o" -exec sh -c '
case "$(head -n 1 "$1")" in
?ELF*) exit 0;;
MZ*) exit 0;;
#!*/ocamlrun*)exit0;;
esac
exit 1
' sh {} \; -print

- 2,885
- 2
- 23
- 27
-
16Only some thousands of cases more, and you will have have reinvented `file`! – tripleee Nov 28 '13 at 07:22
-
@tripleee +1. Cool would be this extension: `find ./ -mime application/x-sharedlib -o -mime application/x-dosexec` – Daniel Alder Sep 15 '14 at 14:36
-
@Daniel Alder, which version of find you use? I did not find option -mime in find (GNU findutils) 4.4.2 – AjayKumarBasuthkar Sep 16 '14 at 16:00
-
@tripleee +1. utilizing 'file' &/ 'mimetype' is good idea or discover find version that supports -mime is better, Also wondering if 'file' / 'mimetype' have option to filter and display only executable(s). – AjayKumarBasuthkar Sep 16 '14 at 21:24
So if you actually want to find executable file types (e.g. scripts, ELF binaries etc.. etc..) not merely files with execution permission then you probably want to do something more like this (where the current directory . can be replaced with whatever directory you want):
gfind . -type f -exec bash -c '[[ $(file -b "'{}'") == *" executable "* ]] ' \; -print
Or for those of you who aren't using macports (linux users) or otherwise have gnu find installed as find you want:
find . -type f -exec bash -c '[[ $(file -b "'{}'") == *" executable "* ]] ' \; -print
Though if you are on OS X it comes with a little utility hidden somewhere called is_exec that basically bundles up that little test for you so you can shorten the command line if you find it. But this way is more flexible as you can easily replace the == test with the =~ test and use it to check for more complex properties like executable plain text files or whatever other info your file command returns.
The exact rules for quotation here are pretty opaque so I just end up working it out by trial and error but I'd love to hear the right explanation.

- 2,288
- 1
- 20
- 28
-
`find . -type f -execdir sh -c "file -b {} | grep -q executable" \; -execdir realpath {} +` let you change `realpath` to something you might want to do with the executable file. Note this won't work with _potentially_ executable file, like `.sh` empty files. – Pablo Bianchi Oct 06 '22 at 04:30
It is SO ridiculous that this is not super-easy... let alone next to impossible. Hands up, I defer to Apple/Spotlight...
mdfind 'kMDItemContentType=public.unix-executable'
At least it works!
-
Good to know about `mdfind` on OSX. Note that uour command reports Unix executables for the _entire system_. `mdfind -onlyin . 'kMDItemContentType=public.unix-executable'` limits results to the current directory's subtree. Minor points of interest: limiting the search to a specific directory only (without subfolders) is apparently not supported. _Symlinks_ to executable files are apparently never included. Curiously, once `mdfind` has found a file to be executable, subsequently _removing_ the executable bit is _not_ picked up. – mklement0 Mar 14 '15 at 01:42
-
I think I've found bugs in how Spotlight detects / undetects executable Unix files; I've filed a bug with Apple, and also at http://www.openradar.me/20162683. I encourage you - and anyone else interested in this functionality - to also file a bug at bug at https://bugreport.apple.com – mklement0 Mar 14 '15 at 03:13
-
(Sorry for the comment flurry; hopefully, they're correct now) `mdfind -onlyin . 'kMDItemContentType=public.unix-executable'` behaves like `find . -type f -perm +111 -print` does. That is, it finds files with _any_ executable bit set, which may yield _false positives_ (though that may not be a problem in practice) - to truly only find files executable by the _current user_ using BSD find, see @gniourf_gniourf's answer. Using a `find`-based solution has the advantage that you can find _symlinks_ to executable files as well, if desired (option `-L`), which `mdfind` seemingly cannot do. – mklement0 Mar 14 '15 at 12:45
-
1@mklement0 my answer eschewed _embellishments_ - to try and nail the point home - but yes, you would almost never use this form "ungarnished". another option - not sure if its come up - is _good old globbing_.. `ls /Applications/**/*(*)` in your (my?) [`zsh` shell](https://www-s.acm.illinois.edu/workshops/zsh/file_gen/file_gen.html) – Alex Gray Mar 19 '15 at 20:31
-
Thanks for the handy `zsh` tip - didn't know that; (seems that you can _either_ match executables (`*`) _or_ symlinks (`@`), but not both, right?). As for your original point: Let me reiterate: `find . -type f -perm +a=x` will do what your `mdfind` command does, while providing more flexibility. You can even reformulate it to be POSIX-compliant. – mklement0 Mar 19 '15 at 20:52
Well the easy answer would be: "your executable files are in the directories contained in your PATH variable" but that would not really find your executables and could miss a lot of executables anyway.
I don't know much about mac but I think "mdfind 'kMDItemContentType=public.unix-executable'" might miss stuff like interpreted scripts
If it's ok for you to find files with the executable bits set (regardless of whether they are actually executable) then it's fine to do
find . -type f -perm +111 -print
where supported the "-executable" option will make a further filter looking at acl and other permission artifacts but is technically not much different to "-pemr +111".
Maybe in the future find will support "-magic " and let you look explicitly for files with a specific magic id ... but then you would haveto specify to fine all the executable formats magic id.
I'm unaware of a technically correct easy way out on unix.

- 716
- 6
- 16
I had the same issue, and the answer was in the dmenu source code: the stest utility made for that purpose. You can compile the 'stest.c' and 'arg.h' files and it should work. There is a man page for the usage, that I put there for convenience:
STEST(1) General Commands Manual STEST(1)
NAME
stest - filter a list of files by properties
SYNOPSIS
stest [-abcdefghlpqrsuwx] [-n file] [-o file]
[file...]
DESCRIPTION
stest takes a list of files and filters by the
files' properties, analogous to test(1). Files
which pass all tests are printed to stdout. If no
files are given, stest reads files from stdin.
OPTIONS
-a Test hidden files.
-b Test that files are block specials.
-c Test that files are character specials.
-d Test that files are directories.
-e Test that files exist.
-f Test that files are regular files.
-g Test that files have their set-group-ID
flag set.
-h Test that files are symbolic links.
-l Test the contents of a directory given as
an argument.
-n file
Test that files are newer than file.
-o file
Test that files are older than file.
-p Test that files are named pipes.
-q No files are printed, only the exit status
is returned.
-r Test that files are readable.
-s Test that files are not empty.
-u Test that files have their set-user-ID flag
set.
-v Invert the sense of tests, only failing
files pass.
-w Test that files are writable.
-x Test that files are executable.
EXIT STATUS
0 At least one file passed all tests.
1 No files passed all tests.
2 An error occurred.
SEE ALSO
dmenu(1), test(1)
dmenu-4.6 STEST(1)

- 11
- 1