5

Если у меня есть список путей, разделенных двоеточиями, очень похоже на $ 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 ${MY_PATH_LIST//[:]/ } -name "$MY_TARGET_FILE" | head -n 1
    

    но это займет много времени, потому что find все еще выполняет исчерпывающий поиск.

    Мне нужно, чтобы это выполнялось быстрее (выход при первом результате), потому что это будет выполняться много раз с другими параметрами.

У кого-нибудь есть лучшее решение, чтобы предложить?

Обратите внимание, что если все не удается, я могу написать решение не Bash. Напишите сейчас, я надеюсь на простое решение с использованием существующих инструментов.

2 ответа2

3

Вы можете просто использовать скрипт, который просто проверяет (-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
0

Используйте голову, чтобы получить первый результат команды поиска.

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .