locate gtags would find all the files named gtags.

What if I only need executables, is there any way to do this?


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 (from locate)
  • read -r line reads one line of input and stores it in a variable called line (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
  • Can you explain the parameters in more detail? – A.B. Mar 30 '15 at 19:01

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 prevents locate 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 from locate 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.

  • I would not exclude executable symlinks matching the filename and add -L just before the {} argument to the find. That's how you would be able to find e.g. gcc. – Adam Ryczkowski Nov 6 '18 at 9:22

short answer, use GNU find:

find / -type f -executable -name '*gtags*'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.