Linux:从指定搜索路径中查找第一个结果

Linux:从指定搜索路径中查找第一个结果

如果我有一个以冒号分隔的路径列表,很像 $PATH,但不一定是 $PATH。

我想在该列表中搜索特定文件名。但是,我只想要第一个匹配的路径。

我考虑过以下Linux命令:

  • which:仅适用于二进制文件,并且仅适用于 $PATH 变量
  • whereis:适用于特定类型的文件,并且仅适用于 $PATH 变量
  • find:不支持冒号分隔的路径列表,并返回多个结果

以下是我尝试过的一些方法:

  1. 我尝试使用whereis以下策略

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

    这几乎可以正常工作。但是,它似乎不会返回任意文件类型的结果。它还会返回多个结果,并且格式很别扭。

  2. which我可以

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

    如果有一个命令行选项强制它允许不可执行文件。

  3. 然后我尝试用 来解决问题find。首先,我使用正则表达式来扩展路径列表(我用空格替换冒号)。然后我调用 find,它工作正常。但是,它会搜索所有路径。我似乎找不到一种方法来告诉它在找到好结果时尽早停止搜索。

    我确实让它工作了

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

    但它需要很长时间才能完成,因为find仍在进行详尽的搜索。

    我需要它执行得更快(第一个结果时退出),因为它将使用不同的参数运行多次。

有人有更好的解决方案可以建议吗?

请注意,如果一切都失败了,我可以编写一个非 bash 解决方案。现在写我希望使用现有工具找到一个简单的解决方案。

答案1

您可以使用一个脚本来简单测试(-e)文件是否存在,并在找到第一个文件时停止:

#!/bin/bash
[[ $# -gt 0 ]] || { echo "Usage: $0 <filename> [pathspec]" >&2 ; exit 1 ; }
if [[ $# -gt 1 ]] ; then
        P="$2"
else
        P="$PATH"
fi

IFS=:
for DIR in $P ; do
        if [[ -e "$DIR/$1" ]] ; then
                echo "$DIR/$1"
                exit 0
        fi
done

例子:

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

$ ./search.sh ls
/Users/danielbeck/bin/ls

$ ./search.sh pwd
/bin/pwd

$ ./search.sh ls /bin
/bin/ls

$ ./search.sh ls /usr/bin:/bin
/bin/ls

答案2

使用 head 获取 find 命令的第一个结果。

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

或者在函数中:

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

答案3

您可以使用该which命令,并PATH仅为该命令的范围设置变量。例如

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

如果存在则返回/path1/file1.txt,否则返回/path2/file1.txt

答案4

以下是如何修复使用 的尝试,find以避免进入子目录并在找到一个文件时停止。诀窍是使用-maxdepth-quit来处理您遇到的问题。如果您还想忽略与搜索名称匹配的子目录,您可以-type f在 之前插入-print

find ${MY_PATH_LIST//[:]/ } -maxdepth 1 -name "$MY_TARGET_FILE" -print -quit

相关内容