List all binaries from $PATH
Good to know this command, and I actually need executables for completion. Maybe I use this command instead.
@vonbrand I’m working on the shell in javascript/php and I’m executing shell in non interactive mode.
Pipe to sort -V for sorted output. Ex: to see all executables in your PATH on your system, and all aliases, all sorted, run: compgen -c | sort -V .
(note that for commands that appear in more than one component of $PATH , they will list only the first one).
If you want the commands without the full paths, and sorted for good measure:
(that is, get the keys of that associative array instead of the values).
@VladimirPanteleev, Same for the other ones. One may argue it’s as expected. If you have a directory in a component of $PATH , you may expect it to be executed. zsh will actually try to execute the /var directory if you enter PATH=/; var for instance (and likely fail as I don’t think any system allows executing directories).
compgen -c will not include directories, so this seems like a zsh bug. If it’s checking if entries are executable, it might as well also check that they’re not directories.
@VladimirPanteleev, in zsh , that’s controlled by the hashexecutablesonly option. Checking the type of files is costly especially on network filesystems as you need one stat() per file in $PATH directories, which is why it’s not enabled by default. That’s generally good enough in the usual case where there’s no garbage in $PATH directories, but you can set that option if $PATH dirs are only on fast filesystems.
In any POSIX shell, without using any external command (assuming printf is built in, if not fall back to echo ) except for the final sorting, and assuming that no executable name contains a newline:
If you have no empty component in $PATH (use . instead) nor components beginning with — , nor wildcard characters \[?* in either PATH components or executable names, and no executables beginning with . , you can simplify this to:
If you’re willing to list the rare non-executable file or non-regular file in the path, there’s a much simpler way:
This skips dot files; if you need them, add the -A flag to ls if yours has it, or if you want to stick to POSIX: ls -aH $PATH | grep -Fxv -e . -e ..
There are simpler solutions in bash and in zsh.
That assumes that $PATH is set and doesn’t contain empty components, and that components don’t look like find predicates (or ls options). Some of those will also ignore dot files.
@StephaneChazelas Yeah, ok. Apart from empty components, this falls squarely under the “don’t do this” category — PATH is under your control.
It still doesn’t work if the empty element is last (as it usually is). (except in yash and zsh in sh emulation).
In your find one. -prune will prevent listing directories. You probably want -L instead of -H as you want to include symlinks (common for executables). -perm -100 gives no guarantee that the file be executable by you (and might (unlikely) exclude executable files).
find $ -maxdepth 1 -executable
The string substitution is used with Bash.
That assumes that $PATH is set, doesn’t contain wildcard or blank characters, doesn’t contain empty components. That assumes GNU find as well. Note that $ is ksh syntax (also supported by zsh and bash). Strictly speaking that also assumes that $PATH components are not find predicates either.
Setting IFS=: is more robust than doing this substitution. Paths with spaces aren’t that uncommon on Windows. Symbolic links are fairly common, but that’s easily solved with -H .
@Gilles: of course. however I don’t see any reasonable use-case for this question, therefore is no need for a bullet-proof answer.
IFS=':';for i in $PATH; do test -d "$i" && find "$i" -maxdepth 1 -executable -type f -exec basename <> \;; done
EDIT: It seems that this is the only command that don’t trigger SELinux alert while reading some of the files in bin directory by apache user.
That assumes that $PATH is set and doesn’t contain wildcard characters and doesn’t contain empty components. That also assumes the GNU implementation of find .
Because of -type f instead of (GNU specific) -xtype f , that will also omit symlinks. That will also not list the content of $PATH components that are symlinks.
If you can run Python 2 in your shell, the following (ridiculously long) one-liner can be used as well:
python2 -c 'import os;import sys;output = lambda(x) : sys.stdout.write(x + "\n"); paths = os.environ["PATH"].split(":") ; listdir = lambda(p) : os.listdir(p) if os.path.isdir(p) else [ ] ; isfile = lambda(x) : True if os.path.isfile(os.path.join(x[0],x[1])) else False ; isexe = lambda(x) : True if os.access(os.path.join(x[0],x[1]), os.X_OK) else False ; map(output,[ os.path.join(p,f) for p in paths for f in listdir(p) if isfile((p,f)) and isexe((p,f)) ])'
This was mostly a fun exercise for myself to see if it could be done using one line of Python code without resorting to using the exec function. In a more readable form, and with some comments, the code looks like this:
import os import sys # This is just to have a function to output something on the screen. # I'm using Python 2.7 in which 'print' is not a function and cannot # be used in the 'map' function. output = lambda(x) : sys.stdout.write(x + "\n") # Get a list of the components in the PATH environment variable. Will # abort the program is PATH doesn't exist paths = os.environ["PATH"].split(":") # os.listdir raises an error is something is not a path so I'm creating # a small function that only executes it if 'p' is a directory listdir = lambda(p) : os.listdir(p) if os.path.isdir(p) else [ ] # Checks if the path specified by x[0] and x[1] is a file isfile = lambda(x) : True if os.path.isfile(os.path.join(x[0],x[1])) else False # Checks if the path specified by x[0] and x[1] has the executable flag set isexe = lambda(x) : True if os.access(os.path.join(x[0],x[1]), os.X_OK) else False # Here, I'm using a list comprehension to build a list of all executable files # in the PATH, and abusing the map function to write every name in the resulting # list to the screen. map(output, [ os.path.join(p,f) for p in paths for f in listdir(p) if isfile((p,f)) and isexe((p,f)) ])
how to find the list of binaries/packages a source provides
Here the source is «linux». Similarly, I remember using a command to get all the packages from the source «linux», which gives all the binaries and packages.
1 Answer 1
You have to use the showsrc subcommand of apt or apt-cache .
See man apt-cache or online for details.
Below is the output from my Ubuntu 16.04 LTS:
$ apt-cache showsrc linux Package: linux Binary: linux-source-4.4.0, linux-doc, linux-headers-4.4.0-21, linux-libc-dev, linux-tools-common, linux-tools-4.4.0-21, linux-cloud-tools-common, linux-cloud-tools-4.4.0-21, linux-image-4.4.0-21-generic, linux-image-extra-4.4.0-21-generic, linux-headers-4.4.0-21-generic, linux-image-4.4.0-21-generic-dbgsym, linux-tools-4.4.0-21-generic, linux-cloud-tools-4.4.0-21-generic, linux-udebs-generic, linux-image-4.4.0-21-generic-lpae, linux-image-extra-4.4.0-21-generic-lpae, linux-headers-4.4.0-21-generic-lpae, linux-image-4.4.0-21-generic-lpae-dbgsym, linux-tools-4.4.0-21-generic-lpae, linux-cloud-tools-4.4.0-21-generic-lpae, linux-udebs-generic-lpae, linux-image-4.4.0-21-lowlatency, linux-image-extra-4.4.0-21-lowlatency, linux-headers-4.4.0-21-lowlatency, linux-image-4.4.0-21-lowlatency-dbgsym, linux-tools-4.4.0-21-lowlatency, linux-cloud-tools-4.4.0-21-lowlatency, linux-udebs-lowlatency, linux-image-4.4.0-21-powerpc-e500mc, linux-image-extra-4.4.0-21-powerpc-e500mc, linux-headers-4.4.0-21-powerpc-e500mc, linux-image-4.4.0-21-powerpc-e500mc-dbgsym, linux-tools-4.4.0-21-powerpc-e500mc, linux-cloud-tools-4.4.0-21-powerpc-e500mc, linux-udebs-powerpc-e500mc, linux-image-4.4.0-21-powerpc-smp, linux-image-extra-4.4.0-21-powerpc-smp, linux-headers-4.4.0-21-powerpc-smp, linux-image-4.4.0-21-powerpc-smp-dbgsym, linux-tools-4.4.0-21-powerpc-smp, linux-cloud-tools-4.4.0-21-powerpc-smp, linux-udebs-powerpc-smp, linux-image-4.4.0-21-powerpc64-emb, linux-image-extra-4.4.0-21-powerpc64-emb, linux-headers-4.4.0-21-powerpc64-emb, linux-image-4.4.0-21-powerpc64-emb-dbgsym, linux-tools-4.4.0-21-powerpc64-emb, linux-cloud-tools-4.4.0-21-powerpc64-emb, linux-udebs-powerpc64-emb, linux-image-4.4.0-21-powerpc64-smp, linux-image-extra-4.4.0-21-powerpc64-smp, linux-headers-4.4.0-21-powerpc64-smp, linux-image-4.4.0-21-powerpc64-smp-dbgsym, linux-tools-4.4.0-21-powerpc64-smp, linux-cloud-tools-4.4.0-21-powerpc64-smp, linux-udebs-powerpc64-smp Version: 4.4.0-21.37 Priority: optional Section: devel .
How to find all binary executables recursively within a directory?
all executable files are listed (excluding directories), and including executable script file (like script.sh, etc). What I want to do is list only binary executable files.
4 Answers 4
You might try the file utility. According to the manpage:
The magic tests are used to check for files with data in particular fixed formats. The canonical example of this is a binary executable (compiled program) a.out file, whose format is defined in , and possibly in the standard include directory.
You might have to play around with the regular expression but something like:
$ find -type f -executable -exec file -i '<>' \; | grep 'x-executable; charset=binary'
file has lots of options, so you might want to take a closer look at the man page. I used the first option I found that seemed to output easily-to-grep output.
I’d say use find -type f -executable -exec sh -c «file -i ‘<>‘ | grep -q ‘x-executable; charset=binary'» \; -print . It will only give you files (and thus can be passed to the next command he wants to run)
serverfault.com/a/584595/211551 solution finds files that are NOT marked executable but are executable.
On OS X, you can install GNU find with brew install findutils or sudo port install findutils and then you can run an invocation like this to a similar effect: gfind . -type f -executable -exec file ‘<>‘ \; | grep -i execut
Here’s a way to exclude scripts, i.e., files whose first two characters are #! :
find -type f -executable -exec sh -c 'test "$(head -c 2 "$1")" != "#!"' sh <> \; -print
For some kinds of files, it’s not clear whether you want them classified as scripts or binary, for example bytecode files. Depending on how things are set up, these may or may not start with #! . If these matter to you, you’ll have to make the inner shell script more complex. For example, here’s how you might include ELF binaries and Mono executables and Objective Caml bytecode programs but not other kinds of executables like shell scripts or perl scripts or JVM bytecode programs:
find -type f -executable -exec sh -c ' case "$(head -n 1 "$1")" in ?ELF*) exit 0;; MZ*) exit 0;; #!*/ocamlrun*) exit 0;; esac exit 1 ' sh <> \; -print