If I have a colon-separated path list, much like $PATH, but not neccessarily $PATH.

I want to search that list for a specific file name. However, I only want the first matching path.

I have considered the following linux commands:

  • which: only works for binary, and only works with $PATH variable
  • whereis: works with particular kinds of files, and only works with $PATH variable
  • find: does not support colon-separated path lists, and returns multiple results

Here are some things I have tried:

  1. I have tried to use whereis by the following strategy

    env WHEREIS="`which whereis`" PATH="$MY_PATH_LIST" $WHEREIS "$TARGET_FILE"

    and this almost works. However, it does not seem to return results for arbitrary file types. It also returns multiple results, and in an awkward format.

  2. I could get which to work by

    env WHICH="`which which`" PATH="$MY_PATH_LIST" $WHICH "$MY_TARGET_FILE"

    if there was a command-line option to force it to allow non-executables.

  3. I then tried to solve the problem with find. First I used regular expressions to expand the path list (I replace colons with spaces). Then I invoke find, and it works correctly. However, it searches all of the paths. I cannot seem to find a way to tell it to stop the search early if it finds a good result.

    I did get this to work

     find ${MY_PATH_LIST//[:]/ } -name "$MY_TARGET_FILE" | head -n 1

    but it takes a long time to complete, because find is still doing an exhaustive search.

    I need this to execute faster (exit on first result), because it would be run many times, with different parameters.

Does anyone have a better solution to suggest?

Note that if all fails, I can write a non-bash solution. Write now I'm hoping for a simple solution using existing tools.

3 Answers 3


You could just use a script that simply tests (-e) for existence of a file and stops when the first one has been found:

[[ $# -gt 0 ]] || { echo "Usage: $0 <filename> [pathspec]" >&2 ; exit 1 ; }
if [[ $# -gt 1 ]] ; then

for DIR in $P ; do
        if [[ -e "$DIR/$1" ]] ; then
                echo "$DIR/$1"
                exit 0


$ ./search.sh 
Usage: ./search.sh <filename> [pathspec]

$ ./search.sh ls

$ ./search.sh pwd

$ ./search.sh ls /bin

$ ./search.sh ls /usr/bin:/bin
  • Thanks, Daniel. This works. I am surprised that there isn't a built-in command for this purpose. I'm going to wait a bit to see if there are any interesting comments. So far, it looks like this one will be going to you. :-) Dec 20, 2012 at 11:35

Use head to get the first result of the find command.

find `echo colon:separated:directories | sed 's/:/ /g'` -name filename | head -n1

Or in a function:

$ function findin { find `echo $1 | sed 's/:/ /g'` -name $2 | head -n1; }
$ findin this:that:other filename

You can use the which command, and set the PATH variable just for the scope of that command. For example

PATH="/path1:/path2" which "file1.txt"

will return /path1/file1.txt if it exists, otherwise /path2/file1.txt if it exists.

  • 1
    Actually no it only works for executable files, as you said. Jun 16, 2021 at 13:00

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.