Рекурсивный поиск двоичного файла в родительских каталогах текущего каталога через иерархический $PATH

Рекурсивный поиск двоичного файла в родительских каталогах текущего каталога через иерархический $PATH

Мне нужно, чтобы при работе в терминале были доступны дополнительные двоичные файлы/команды, запускаемые CWD.

В качестве примера приведем следующую структуру каталогов:

├── P1
|   ├── mybin
|   │   └── cmd1
|   ├── S1
|   │   └── mybin
|   │       └── cmd2
|   ├── S2
└── P2
    └── S3

Затем в этой структуре каталогов

  • cmd1и cmd2доступны в формате P1/S1.
  • cmd1доступен только в P1или P1/S2.
  • ни один из них не доступен в P2илиP2/S3

В общем, я хочу, чтобы это работало с любой структурой каталогов. Это похоже на то, как git определяет, находитесь ли вы в репозитории git. Это эквивалентно добавлению ./mybin, ../mybin, ../../mybinв $PATH.

Как мне изменить мой PATH, чтобы это работало? Я использую оболочку fish, но я с радостью перенесу решение из любой другой оболочки в свою.

решение1

Я понимаю, что вас не устраивает только

PATH="./mybin:../mybin:../../mybin:../../../mybin:$PATH"

до некоторого предела, например, 8 или около того подкаталогов.

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

Например, k fooпопробуем ./mybin/foo, ../mybin/fooи т.д., но просто fooбудем искать в $PATH, как обычно.

Но я не использую fish, и я не представляю, как это можно написать на языке оболочки fish. С bash / ksh / zsh это может быть что-то вроде:

function k {
    typeset p=. cmd=$1; shift
    while
        typeset e=$p/mybin/$cmd
        if [ -x "$e" ]; then "$e" "$@"; return; fi 
        [ ! "$p" -ef / ]
    do
        p=../$p
    done
    echo >&2 "k: not found: $cmd"; return 1
}

Если это сработает, вы можете превратить его в автономный исполняемый скрипт, вместо того, чтобы пытаться преобразовать его в fish:

#! /bin/bash
p=. cmd=$1; shift
while
    e=$p/mybin/$cmd
    if [ -x "$e" ]; then exec "$e" "$@"; fi
    [ ! "$p" -ef / ]
do
    p=../$p
done
echo >&2 "k: not found: $cmd"; exit 1

Связанный контент