0$ будут всегда включать путь к сценарию?

Незначительные выпуски могут быть обновлены с yum команда:

yum upgrade

Если Вы захотите использовать файлы на DVD, то необходимо будет определить другой локальный вкусный репозиторий в /etc/yum.repos.d/ (например, dvd.repo):

[rhel-cd]
name=Red Hat Enterprise Linux $releasever - $basearch - CD
baseurl=file:///media/RHEL/Server/
enabled=1
gpgcheck=0

Займите место baseurl с точкой монтирования DVD

10
23.05.2017, 15:40
7 ответов

Ноль произвольного аргумента может быть указан при использовании опции [11669]-c[11670] в большинстве (всех?) оболочек. Eg:

Из [11671]man bash[11672] (выбрано исключительно потому, что это имеет лучшее описание, чем мой [11673]man sh[11674] - использование одинаково независимо):

-c

Если опция -c присутствует, то команды читаются из первой строки command_string аргумента без опции. Если после аргумента command_string есть аргументы, то они следующие назначенные позиционным параметрам, начиная с $0.

:help :botright
:help :saveas
:help :split
3
27.01.2020, 19:59

ПРИМЕЧАНИЕ: Другие уже объяснили механику $ 0 , поэтому я пропущу все это.

Я обычно обхожу эту проблему в сторону и просто использую команду readlink -f $ 0 . Это всегда будет возвращать вам полный путь того, что вы дадите ему в качестве аргумента.

Примеры

Скажем, я здесь, чтобы начать с:

$ pwd
/home/saml/tst/119929/adir

Создайте каталог + файл:

$ mkdir adir
$ touch afile
$ cd adir/

Теперь начните показывать ссылку для чтения :

$ readlink -f ../adir
/home/saml/tst/119929/adir

$ readlink -f ../
/home/saml/tst/119929

$ readlink -f ../afile 
/home/saml/tst/119929/afile

$ readlink -f .
/home/saml/tst/119929/adir

Дополнительные уловки

Теперь с согласованный результат, возвращаемый, когда мы запрашиваем $ 0 через readlink , мы можем использовать просто dirname $ (readlink -f $ 0) , чтобы получить абсолютный путь к скрипту -или- basename $ (readlink -f $ 0) , чтобы получить фактическое имя сценария.

3
27.01.2020, 19:59

На моей странице man написано:

$0 : расширяется до имени shell или shell script.

Похоже, это переводится как argv[0] текущей оболочки - или первый неоперанд аргумент командной строки, который интерпретируемая в данный момент оболочка получает при вызове. Ранее я утверждал, что sh ./somescript передаст свою $0 $ENV переменную в sh но это было неверно, поскольку shell является новым процессом и вызывается с новым $ENV.

Таким образом sh ./somescript.sh отличается от . ./somescript.sh который запускается в текущем окружении и $0 уже установлен.

Вы можете проверить это, сравнив $0 с /proc/$$/status.

echo 'script="/proc/$$/status"
    echo $0
    cat "$script"' \
    > ./script.sh
sh ./script.sh ; . ./script.sh

Спасибо за исправление, @toxalot. Я кое-чему научился.

0
27.01.2020, 19:59

Вот две ситуации, когда каталог не будет включен:

> bash scriptname
scriptname

> bash <scriptname
bash

В обоих случаях текущим каталогом должен быть каталог, в котором находится scriptname.

В первом случае значение $0 все равно может быть передано в grep, поскольку он предполагает, что аргумент FILE относится к текущему каталогу.

Во втором случае, если справка и информация о версии печатается только в ответ на определенную опцию командной строки, это не должно быть проблемой. Я не уверен, зачем кому-то вызывать сценарий таким образом для печати справки или информации о версии.

Предостережения

  • Если сценарий изменяет текущий каталог, вы не захотите использовать относительные пути.

  • Если сценарий является исходным, значение $0 обычно будет вызывающим сценарием, а не исходным.

6
27.01.2020, 19:59

Для чего-то подобного я использую:

rPath="$(dirname $(realpath $0))"
echo $rPath 

rPath=$(dirname $(readlink -e -- "$0"))
echo $rPath 

rPath всегда имеет одно и то же значение.

0
27.01.2020, 19:59

В наиболее распространенных случаях $ 0 будет содержать путь, абсолютный или относительный к сценарию, поэтому

script_path=$(readlink -e -- "$0")

( при условии, что есть команда readlink и она поддерживает -e ), как правило, это достаточно хороший способ получить канонический абсолютный путь к сценарию.

$ 0 назначается из аргумента, определяющего сценарий, переданный интерпретатору.

Например, в:

the-shell -shell-options the/script its args

$ 0 получает сценарий / .

Когда вы запустите:

the/script its args

Ваша оболочка выполнит:

exec("the/script", ["the/script", "its", "args"])

Если сценарий содержит #! / bin / sh - she-bang, например, система преобразует это в:

exec("/bin/sh", ["/bin/sh" or "the/script", "-", "the/script", "its", "args"])

(если он не содержит she-bang, или, в более общем смысле, если система возвращает ошибку ENOEXEC, то это ваш оболочка, которая будет делать то же самое)

В некоторых системах есть исключение для сценариев setuid / setgid, когда система открывает сценарий на некотором fd x и запускает вместо этого:

exec("/bin/sh", ["/bin/sh" or "the/script", "-", "/dev/fd/x", "its", "args"])

чтобы избежать состояния гонки (в этом случае $ 0 будет содержать / dev / fd / x ).

Теперь вы можете возразить, что / dev / fd / x - это путь к этому сценарию. Однако обратите внимание, что если вы читаете из $ 0 , вы сломаете скрипт по мере использования ввода.

Теперь есть разница, если имя вызываемой команды сценария не содержит косой черты. В:

the-script its args

Ваша оболочка будет искать скрипт в $ PATH . $ PATH может содержать абсолютные или относительные (включая пустую строку) пути к некоторым каталогам. Например, если $ PATH содержит / bin: / usr / bin: и сценарий находится в текущем каталоге, оболочка выполнит следующее:

exec("the-script", ["the-script", "its", "args"])

, который станет:

exec("/bin/sh", ["/bin/sh" or "the-script", "-", "the-script", "its", "args"]

Или, если он найден в / usr / bin :

exec("/usr/bin/the-script", ["the-script", "its", "args"])
exec("/bin/sh", ["/bin/sh" or "the-script" or "/usr/bin/the-script",
     "-", "/usr/bin/the-script", "its", "args")

Во всех вышеупомянутых случаях, кроме углового случая setuid, $ 0 будет содержать путь (абсолютный или относительный) к скрипту.

Теперь сценарий также может называться:

the-interpreter the-script its args

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

Старые реализации AT&T ksh фактически безоговорочно искали сценарий в $ PATH (что на самом деле было ошибкой и дырой в безопасности для сценариев setuid), поэтому $ 0 на самом деле не содержал путь к сценарию, если только поиск $ PATH действительно не нашел the-script в текущем каталоге.

Более новый AT&T ksh будет пытаться интерпретировать сценарий в текущем каталоге, если он доступен для чтения. В противном случае он будет искать читаемый и исполняемый скрипт в $ PATH .

Для bash он проверяет, находится ли the-script в текущем каталоге (и не является ли неработающая символическая ссылка), и если нет, ищет читаемый (не обязательно исполняемый) сценарий в $ PATH .

zsh в эмуляция sh будет работать так же, как bash , за исключением того, что если the-script является неработающей символической ссылкой в ​​текущем каталоге, она не будет найдите сценарий в $ PATH и вместо этого сообщит об ошибке.

Все другие оболочки, подобные Борну, не ищут скрипт в $ PATH .

В любом случае, для всех этих оболочек, если вы обнаружите, что $ 0 не содержит / и не читается, то, вероятно, он был найден в $ PATH .Затем, поскольку файлы в $ PATH , вероятно, будут исполняемыми, вероятно, будет безопасным приближением использовать команду -v - "$ 0" , чтобы найти его путь (хотя это не работают, если $ 0 также является именем встроенной оболочки или ключевым словом (в большинстве оболочек)).

Итак, если вы действительно хотите прикрыть этот случай, вы можете написать его:

progname=$0
[ -r "$progname" ] || progname=$(
    IFS=:; set -f
    for i in ${PATH-$(getconf PATH)}""; do
      case $i in
        "") p=$progname;;
        */) p=$i$progname;;
        *) p=$i/$progname
      esac
      [ -r "$p" ] && exec printf '%s\n' "$p"
    done
    exit 1
  ) && progname=$(readlink -e -- "$progname") ||
  progname=unknown

( "" , добавленный к $ PATH , чтобы сохранить конечный пустой элемент с оболочки, у которых $ IFS действует как разделитель вместо разделителя ).

Теперь,есть более эзотерические способы вызвать сценарий. Можно сделать:

the-shell < the-script

Или:

cat the-script | the-shell

В этом случае $ 0 будет первым аргументом ( argv [0] ), который получил интерпретатор (выше the-shell , но это может быть что угодно, хотя обычно это либо базовое имя, либо один путь к этому интерпретатору).

Определение того, что вы находитесь в такой ситуации, по значению $ 0 ненадежно. Вы можете посмотреть на вывод ps -o args = -p "$$" , чтобы получить подсказку. В случае с конвейером нет реального способа вернуться к пути к скрипту.

Можно также сделать:

the-shell -c '. the-script' blah blih

Тогда, за исключением zsh (и некоторой старой реализации оболочки Bourne), $ 0 будет бла . Опять же, трудно найти путь к сценарию в этих оболочках.

Или:

the-shell -c "$(cat the-script)" blah blih

и т. Д.

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

progname=$0
[ -r "$progname" ] || progname=$(
    IFS=:; set -f
    for i in ${PATH-$(getconf PATH)}:; do
      case $i in
        "") p=$progname;;
        */) p=$i$progname;;
        *) p=$i/$progname
      esac
      [ -r "$p" ] && exec printf '%s\n' "$p"
    done
    exit 1
  ) && progname=$(readlink -e -- "$progname") ||
  progname=unknown

[ -f "$progname" ] && grep -q 7YQLVVD3UIUDTA32LSE8U9UOHH < "$progname" ||
  progname=unknown

Но опять же, я не думаю, что это того стоит.

17
27.01.2020, 19:59

Я хочу grep текущего скрипта, чтобы я мог распечатать справку и версию информация из раздела комментариев вверху.

Хотя $ 0 содержит имя сценария, он может содержать путь с префиксом в зависимости от способа вызова сценария, я всегда использовал $ {0 ## * /} для печати имя сценария в выводе справки, которое удаляет любой начальный путь из $ 0 .

Взято из Advanced Bash Scripting guide - Раздел 10.2. Подстановка параметров

$ {var # Pattern}

Удаление из $ var самой короткой части $ Pattern , который соответствует внешнему интерфейсу $ var .

$ {var ## Pattern}

Удалите из $ var самую длинную часть $ Pattern , которая соответствует передней части $ var .

Таким образом, самая длинная часть $ 0 , которая соответствует * / , будет префиксом всего пути, возвращающим только имя сценария.

0
27.01.2020, 19:59

Теги

Похожие вопросы