7

Как узнать имя скрипта в Bash?

1

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

Допустим, мой скрипт находится в файле runme.sh, как мне сделать так, чтобы он выводил сообщение "Вы запускаете runme.sh", не зашивая это имя в код?

5 ответ(ов)

8

Команда me=$(basename "$0") позволяет получить имя текущего скрипта. Однако, если ваш скрипт запускается через символическую ссылку, это может быть не тем, что вы хотите, поскольку пользователь может запутаться, видя такое поведение.

Чтобы учесть возможность выполнения скрипта через символическую ссылку, можно использовать следующую конструкцию:

me="$(basename "$(test -L "$0" && readlink "$0" || echo "$0")")"

Тем не менее, на мой взгляд, это создаст путаницу. "Я запустил foo.sh, а он говорит, что я запускаю bar.sh!? Это должно быть багом!" Кроме того, одна из причин использования разных имен для символических ссылок заключается в том, чтобы предоставить различный функционал в зависимости от того, под каким именем был вызван скрипт (например, gzip и gunzip на некоторых платформах).


1 Это означает, что если вы хотите разрешить символические ссылки, когда пользователь выполняет foo.sh, который на самом деле является символической ссылкой на bar.sh, вам следует использовать разрешенное имя bar.sh, а не foo.sh.

3

В этом скрипте на Bash отображаются переданные аргументы и информация о самом скрипте. Давайте разберем его шаг за шагом и посмотрим на результаты.

  1. Скрипт начинается с интерпретатора: Первая строка #!/bin/bash указывает, что скрипт должен выполняться в оболочке Bash.

  2. Вывод информации:

    • Скрипт выводит информацию об аргументах, переданных при его вызове, а также о пути к самому скрипту и его имени.
    • Используются специальные переменные:
      • ${@} — все переданные аргументы.
      • $1 и $2 — первый и второй аргументы соответственно.
      • ${0} — путь к скрипту.
      • ${0%/*} — родительский путь к директории, где находится скрипт.
      • ${0##*/} — само имя скрипта.
  3. Пример вызова:

    /misc/shell_scripts/check_root/show_parms.sh "'hello there'" "'william'"
    

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

  4. Результаты выполнения: При запуске с указанными аргументами вывод будет следующим:

    # arguments called with --->  'hello there' 'william'
    # $1 ---------------------->  'hello there'
    # $2 ---------------------->  'william'
    # path to me -------------->  /misc/shell_scripts/check_root/show_parms.sh
    # parent path ------------->  /misc/shell_scripts/check_root
    # my name ----------------->  show_parms.sh
    

Это демонстрирует, что аргументы передаются корректно, включая строки с пробелами, если они заключены в кавычки. Также выводятся пути, так что можно легко понять, где находится сам скрипт. Если у вас есть дополнительные вопросы по этому скрипту, не стесняйтесь спрашивать!

2

С версии bash >= 3 следующий код работает:

$ ./s
0 is: ./s
BASH_SOURCE is: ./s
$ . ./s
0 is: bash
BASH_SOURCE is: ./s

$ cat s
#!/bin/bash

printf '$0 is: %s\n$BASH_SOURCE is: %s\n' "$0" "$BASH_SOURCE"

При запуске скрипта ./s, переменная $0 содержит имя запускаемого скрипта (то есть ./s), а переменная $BASH_SOURCE также указывает на имя скрипта. Когда вы запускаете скрипт с помощью source (или .), $0 становится bash, так как в этом случае выполняется интерактивная оболочка, а $BASH_SOURCE по-прежнему ссылается на оригинальный файл скрипта ./s. Это поведение связано с тем, как Bash обрабатывает контекст выполнения скриптов.

1

$BASH_SOURCE возвращает корректный путь к файлу при его "подгрузке" (sourcing). Однако, это значение включает полный путь к скрипту. Чтобы получить только имя файла скрипта без пути, используйте команду:

$(basename $BASH_SOURCE)
0

Если имя скрипта содержит пробелы, более надежным способом будет использовать "$0" или "$(basename "$0")" — или на MacOS: "$(basename \"$0\")". Это предотвратит искажение или некорректную интерпретацию имени. В общем, хорошей практикой является всегда заключать имена переменных в двойные кавычки в оболочке.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь