How can I find only the executable files under a certain directory in Linux?
9 Answers
Checking for executable files can be done with -perm (not recommended) or -executable (recommended, as it takes ACL into account). It's a GNU extension also available on FreeBSD.
To use the -executable option:
find DIR -executable
If you want to find only executable files and not searchable directories, combine with -type f:
find DIR -executable -type f
- 5,693
- 4,072
Use the find's -perm option. This will find files in the current directory that are either executable by their owner, by group members or by others:
find . -perm /u=x,g=x,o=x
Edit:
I just found another option that is present at least in GNU find 4.4.0:
find . -executable
This should work even better because ACLs are also considered.
- 10,412
I know the question specifically mentions Linux, but since it's the first result on Google, I just wanted to add the answer I was looking for.
This is tested on macOS 10.12.5:
find . -perm +111 -type f
- 58,727
- 1,112
I have another approach, in case what you really want is just to do something with executable files--and not necessarily to actually force find to filter itself:
for i in `find . -type f`; do [ -x $i ] && echo "$i is executable"; done
I prefer this because it doesn't rely on -executable which is platform specific; and it doesn't rely on -perm which is a bit arcane, a bit platform specific, and as written above requires the file to be executable for everyone (not just you).
. will start searching the current directory. This can be replaced with any directory path.
The -type f is important because in *nix directories have to be executable to be traversable, and the more of the query is in the find command, the more memory efficient your command will be.
Anyhow, just offering another approach, since *nix is the land of a billion approaches.
- 184
- 226
A file marked executable need not be a executable or loadable file or object.
Here is what I use:
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
As a fan of the one liner...
find /usr/bin -executable -type f -print0 | xargs file | grep ASCII
Using 'xargs' to take the output from the find command (using print0 to ensure filenames with spaces are handled correctly). We now have a list of files that are executable and we provide them, one by one, as the parameter for the 'file' command. Then grep for the term ASCII to ignore binaries. Please substitute -executable in find command with what style you prefer (see earlier answers) or what works on your 'NIX OS
I required the above to find files with eval in scripts owned by root, so created the following to help find priv escalation weaknesses where root user runs scripts with unsafe parameters...
echo -n "+ Identifying script files owned by root that execute and have an eval in them..."
find / -not \( -path /proc -prune \) -type f -executable -user root -exec grep -l eval {} \; -exec file {} \; | grep ASCII| cut -d ':' -f1 > $outputDir"/root_owned_scripts_with_eval.out" 2>/dev/null &
I created a function in ~/.bashrc tonight to find executable files not in the system path and not directories:
# Quickly locate executables not in the path
xlocate () {
locate -0r "$1" | xargs -0 -I{} bash -c '[[ -x "$1" ]] && [[ ! -d "$1" ]] \
&& echo "executable: $1"' _ {}
} # xlocate ()
The advantage is it will search three Linux distros and a Windows installation in under a second where the find command takes 15 minutes.
For example:
$ time xlocate llocate
executable: /bin/ntfsfallocate
executable: /home/rick/restore/mnt/e/bin/llocate
executable: /mnt/clone/bin/ntfsfallocate
executable: /mnt/clone/home/rick/restore/mnt/e/bin/llocate
executable: /mnt/clone/usr/bin/fallocate
executable: /mnt/e/bin/llocate
executable: /mnt/old/bin/ntfsfallocate
executable: /mnt/old/usr/bin/fallocate
executable: /usr/bin/fallocate
real 0m0.504s
user 0m0.487s
sys 0m0.018s
Or for a whole directory and all it's subs:
$ time xlocate /mnt/e/usr/local/bin/ | wc -l
65
real 0m0.741s
user 0m0.705s
sys 0m0.032s
- 205
This finds the word executable in the output of "file". You could also grep for "ELF". This will find binary executable files if they have +x (executable bit) set or not. Here's my variation.
find . | while read a; do [[ $(file -b "$a" | grep executable) != "" ]] && echo $a; done
- 141
fd -tx
fd is a simple user friendly alternative to find written in rust.
You may need to install it as it is not included in POSIX standard.
- 101