How can I find only the executable files under a certain directory in Linux?
For anyone wanting to do this on a Mac (tested on OS X 10.9.5): ls -l | egrep ‘^[^d]..x..x..x.*$’ The above will list all executables (for all/user and group) in the current directory. Note: The -executable option does not work on a Mac hence the above workaround.
@techfoobar: The question is ambiguous: Does it mean files that contain executable code, or does it mean files that have executable permission? But even if we assume that executable permission is what is wanted (as the majority of the responses seem to), the question doesn’t say world-executable. Your solution will find files (and also fifos, sockets, symlinks, etc.) that have world execute permission, but not 750 ( -rwxr-x— ), which is still executable to some users.
8 Answers 8
Checking for executable files can be done with -perm (not recommended) or -executable (recommended, as it takes ACL into account). To use the -executable option:
If you want to find only executable files and not searchable directories, combine with -type f :
find DIR -executable -type f
a shebang doesn’t mean they’re executable. it tells us only which interpreter to use. and by linux definition “executable files” are files with the executable (x) bit set
What version of find supports that type for -type? man find lists b, c, d, p, f, l, s and D on my system.
If you have an old version of find (probably before 4.3.8) which lacks -executable use find . -perm /u=x,g=x,o=x.
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:
I just found another option that is present at least in GNU find 4.4.0:
This should work even better because ACLs are also considered.
This only works on a newer version of find. The one that comes by default with CentOS gives the error find: invalid mode /u=x,g=x,o=x’`
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 (for example if you are — like me at the moment — forced by your employer to use a non GNU/Linux system).
Tested on macOS 10.12.5
from the man page -perm +mode This is no longer supported (and has been deprecated since 2005). Use -perm /mode instead.
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).
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.
(0) Which do you prefer, arcane and correct or intuitive and flawed? I prefer correct. (1) innaM’s answer, featuring find -perm , finds files that have any execute permission bit set. (2) By contrast, this answer finds only files for which the current user has execute permission. Granted, that might be what the OP wants, but it’s unclear. … (Cont’d)
(Cont’d) … (3) For clarity, you might want to change `…` to $(…) — see this, this, and this. (4) But don’t do for i in $(find …); do … ; it fails on filenames that contain space(s). Instead, do find … -exec … . (5) And, when you do work with shell variables, always quote them (in double quotes) unless you have a good reason not to, and you’re sure you know what you’re doing.
@scott OK, I stand corrected 🙂 I read the -perm argument as requiring all three, not one of them. Also, thank you for the input on protecting shell arguments, that’s all stuff I wasn’t aware of.
@MarkMcKenna you have a typo in there: for i in find . -type f ; do [ -x $i ] && echo «$i is executable»; done ; you are missing the
A file marked executable need not be a executable or loadable file or object.
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
@DerMike, It is one of the ways to find executable in current directory, including .so files, even if a file is not marked executable it can discover.
@nonchip I strongly disagree. @OP did not ask what files were set to executable/+x, but what files were actually executable. The definition of what that means is left to the reader, but I would not consider portrait.png executable, even with a+x , and I would consider /usr/bin/grep an executable, even if it was accidentally changed to miss the x flag.
The downvotes you’ve gotten so far reflect the belief that you’re answering the wrong question with a skimpy explanation. I wonder why you consider .so files to be executable but not .o files, and why you consider OCaml scripts to be executable but not shell scripts (or Awk, Perl, Python, etc.). Also, your answer has a typo. But THIS downvote is for the snarky, abusive comment.
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 &
Unix standard directory to put custom executables or scripts? [closed]
If I have a custom shell script or program that I created myself or downloaded from the web and I want to be able to execute this from the CLI, is there the standard location to put this in Linux/Unix directory structure?
/usr/bin ? /usr/local/bin ? /usr/lib ? /usr/sbin ? /bin ? /sbin ? /var ?
I usually put it under my ~/bin directory and add it to the PATH, but it doesn’t seem clean. And every time I download a new program, I have to add it to the PATH again.
If your ~/bin is on the PATH, then all programs you put in ~/bin should also be on your path. What do you mean you have to put it on the PATH again?
You would have to do the same no matter where you put it then. If you put /usr/bin/xyz, then you’d have to add that to the path also.
Well, ok, ignoring the PATH issue. Would it be better to put it in ~/bin or /usr/bin? Just want to know if there’s the standard/cleaner way of organizing downloaded apps.
2 Answers 2
/usr/local/bin exists precisely for this purpose: for system-wide installation. For your own private use, ~/bin is the de facto standard.
If you want to keep each binary in its own subdirectory, you can do that, and add a symlink to a directory already in your PATH . So, for example:
curl -o $HOME/downloads/fnord http://fnord.example.com/script.exe ln -s $HOME/downloads/fnord $HOME/bin/
This assumes $HOME/bin is in your PATH .
There are tools like stow which do this — and much more — behind the scenes for you.
As a tip for Mac users: If you choose ´~/bin´ and don’t want this directory to show up i Finder, you can make it invisible with SETFILE(1): ´setfile -a V ~/bin´ for making invisible and ´setfile -a v ~/bin´ for making visible again. Note that this requires the Xcode Tools.
@tripleee: Is there a de facto standard directory for scripts (bash, perl, etc.) ? I’m thinking of e.g. ~/etc? The point is that you do not backup/track with a cvs/.. in the same way scripts and binaries.
@phs bin is for all kinds of executables, scripts or proper binaries. If you want them under direct version control, putting all of your bin in version control is certainly an option; though more commonly, you have a separate project for each, or at least each distinct group. When you release a new version, install it into your own bin . Or if you’re serious about dog-fooding and/or have too few surprises in your life, put a symlink to your development version in your bin .
Thanks, I did a ln -s /usr/local/bin /root/ to better keep track of executables and respect both standards 😉
@capitano666 Not sure what you means with «both standards». The home directory of root should normally contain very little, as it’s for stuff which is useful to root only.
This may vary slightly depending on the Unix flavour. I’m assuming Linux here (although this could apply to OSX). According to the Filesystem Hierarchy Standard (FHS) (link obtained from the Linux Standard Base working group):
The /usr/local hierarchy is for use by the system administrator when installing software locally. It needs to be safe from being overwritten when the system software is updated. It may be used for programs and data that are shareable amongst a group of hosts, but not found in /usr .
Locally installed software must be placed within /usr/local rather than /usr unless it is being installed to replace or upgrade software in /usr .
/usr/local/bin is often on the path by default.
Note that you should only put the executable or a link to it in /usr/local/bin , the rest may have to go in /usr/local/lib or /usr/local/share .
The /opt tree might also be sensible:
/opt is reserved for the installation of add-on application software packages.
A package to be installed in /opt must locate its static files in a separate /opt/ or /opt/ directory tree, where is a name that describes the software package and is the provider’s LANANA registered name.
[. ]
The directories /opt/bin, /opt/doc, /opt/include, /opt/info, /opt/lib, and /opt/man are reserved for local system administrator use. Packages may provide «front-end» files intended to be placed in (by linking or copying) these reserved directories by the local system administrator, but must function normally in the absence of these reserved directories.
(You could make your own link from /opt/your-package/bin/executable into /opt/bin , and put /opt/bin on the PATH if it’s not already there.)