Как задать относительный путь в bash-скрипте относительно места его выполнения?

У меня есть следующая структура директорий: 

```
~/AAA
~/AAA/bash
~/AAA/site

~/BBB
~/BBB/bash
~/BBB/site

~/NNN
~/NNN/bash
~/NNN/site
```

Внутри директории `bash/` всегда находятся файлы с расширением `.sh`. Обычно я работаю в директории `site/`. Я создал файл с алиасами `~/.bash_aliases`, где указал следующее:

```bash
alias get1="bash ../bash/111.sh"
alias get2="bash ../bash/222.sh"
alias getN="bash ../bash/NNN.sh"
```

**Первая проблема.** В каждом скрипте есть файл с переменными, который я подключаю с помощью:

```bash
. ./variables.sh
```

Однако, когда я запускаю алиас, например, `get1`, я получаю сообщение об ошибке: `variables.sh: No such file or directory`. Я понимаю, что можно использовать абсолютный путь, но возможно ли сделать код универсальным, чтобы не прописывать абсолютный путь в каждом файле?

**Второй вопрос.** Возможно ли настроить алиас так, чтобы он правильно работал, независимо от того, в какой поддиректории корневой директории я нахожусь, например, в `~/BBB` или `~/BBB/bash`? Хочу, чтобы, находясь внутри `~/BBB`, я мог запускать скрипты из `~/BBB/bash/` независимо от уровня вложенности.

Кроме того, если бы я скопировал директорию `bash/` в новую директорию `~/CCC/`, я хотел бы, чтобы скрипты продолжали работать без изменений. 

Если это возможно, что мне нужно сделать и что искать?
  • 22 апреля 2025 г. 14:55
Ответы на вопрос 2
Для решения ваших задач в bash, вам нужно использовать относительные пути и знать местоположение скрипта, который вы запускаете. Это можно сделать с помощью переменной `$BASH_SOURCE` и встроенной команды `dirname`. Вот как можно организовать решение по двум вашим вопросам:

### 1. Решение проблемы с подключением файла `variables.sh`

Когда вы запускаете скрипт через алиас, текущая директория остается той, где вы запускали команду, а не тем местом, где находится файл скрипта. Чтобы подключить `variables.sh` корректно, нужно использовать `dirname` для получения пути к вашему скрипту и затем разделить его на части:

Вместо:

```bash
. ./variables.sh
```

Используйте:

```bash
. "$(dirname "${BASH_SOURCE[0]}")/variables.sh"
```

Это гарантирует, что путь к `variables.sh` будет корректным независимо от того, где запущен ваш aliass.

### 2. Сделать алиасы универсальными

Теперь вам нужно настроить ваши алиасы так, чтобы они правильно работали, независимо от текущей директории. Вы можете создать функцию в вашем `.bash_aliases`, которая будет запускать скрипт `111.sh`, `222.sh` и `NNN.sh` из директории `bash`, находясь в любой поддиректории.

Вот пример, как это можно сделать:

```bash
get_script() {
    local script_name="$1"
    local script_path="$(dirname "$(realpath "$0")")/../bash/${script_name}.sh"
    bash "$script_path"
}

alias get1='get_script 111'
alias get2='get_script 222'
alias getN='get_script NNN'
```

В этом примере функция `get_script` получает имя скрипта, формирует путь к нему и запускает его. Строка `realpath "$0"` возвращает абсолютный путь к текущей директории, где находится скрипт, что позволяет сгенерировать корректный путь к скрипту в `bash`.

### 3. Как это работает в разных директориях

Этот подход работает независимо от того, где вы находитесь, потому что `realpath` обеспечит корректное определение пути относительно директории, где был вызван скрипт. Таким образом, если вы скопируете папку `bash` в другую директорию, скрипты будут продолжать работать, так как путь формируется динамически.

### Заключение

Таким образом, вы можете легко управлять путями к вашим скриптам и использовать алиасы, которые будут работать в любой директории без необходимости прописывать абсолютные пути.
Внутри каждого скрипта есть файл с переменными.
Я подключаю его так:
. ./variables.sh

Но при запуске алиаса, например get1, я получаю сообщение об ошибке: variables.sh: No such file or directory.
Сменяйте рабочий каталог на тот, из которого запускается скрипт.
cd $(dirname $(realpath $0))
./variables.sh


А нельзя ли сделать путь внутри алиаса таким, чтобы находясь в любой поддириктории корневой директории, например в ~/BBB, или в ~/BBB/bash, алиас срабатывал верно?
В алиасе пропишите абсолютный путь. Скрипты будут универсальные, алиасы не универсальные.
Либо напишите один скрипт, который будет запускать любые по параметру:
вместо get1 будете вызывать get 1
а внутри
[ -d ~/$1/bash ] || (echo "нет каталога"; exit 1)
[ -f ~/$1/bash/$1.sh ] || (echo "нет скрипта"; exit 2)
echo "запускаю"
~/$1/bash/$1.sh
т.е. по get 123 будет запущено ~/123/bash/123.sh
Похожие вопросы