How find only executable files using 'locate'?
Not easily. You can use
locate bash | while IFS= read -r line; do [[ -x "$line" ]] && echo $line; done
to find all executables where the name contains bash
. This is faster than using find
across the whole filesystem because only a few files need to be checked.
locate bash
does what it always does (lists all matches)|
(pipe) takes the output from the first command (locate
) and sends it to the second one (the rest of the line)- the
while ...; do ... done
loop iterates over every line it receives from the pipe (fromlocate
) read -r line
reads one line of input and stores it in a variable calledline
(in our case, a path/file name)[[ -x "$line" ]]
tests whether the file in$line
is executable- if it is, the
&& echo $line
part prints it on your screen
The fastest and least expensive solution:
locate -b '\gtags' | xargs -ri find {} -prune -type f -executable
According to the xargs
man page, the above syntax passes all filenames found by locate
to a single execution of find
, which examines only the specified files.
This solution is better than those given previously because:
- Using
find
to search every file on the system beginning with the root directory may be a short command, but it could take a very long time to run. - Using a shell while-loop to check each filename can be slow, because it checks each file one at a time.
Since others have asked for detailed explanations of the parameters given in earlier answers, the details are:
locate
(See: Invoking locate - Finding Files)-b
: Match only the base filename of the pathname against the specified patterns, don't consider the names of the directories in the pathname.\
: Since the backslash is a globbing character, it preventslocate
from treating the pattern,gtags
, as though it were*gtags*
. I.e., it looks for files that have the exact name "gtags" without other characters before or after.
xargs
(See: xargs options - Finding Files)-r
: If the standard input is completely empty, do not run the command.-i
: Substitute{}
in the following command with the list of filenames read from standard input.
find
(See: find Primary Index - Finding Files){}
:xargs
substitutes this with the names of all the files it receives fromlocate
on standard input.find
searches all of those files for matches to the following expressions and if any of them are directories, it examines the contents of them, too.-prune
: If a filename being evaluated belongs to a directory, don't search its contents.-type f
: Include in the output only filenames that belong to "regular" files, not special ones like devices, named pipes, etc.-executable
: Include in the output only filenames of executable files. That is, those with one or more of their executable mode bits set, regardless of the file content.
In short, locate
prints the names of matching files to standard output, which is piped (using |
) into the standard input of xargs
. xargs
reads the filenames from standard input and combines them into a space-delimited list in a single string. If the string is not empty, xargs
substitutes the string for {}
in the find
command before executing it.
short answer, use GNU find:
find / -type f -executable -name '*gtags*'