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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .