Что делает $ {0% / *} в сценариях оболочки?


17

Извините, если это глупый вопрос, но я безуспешно искал его.

Что именно делает вторая строка?

#!/bin/sh
cd ${0%/*} || exit 1

Я знаю, что первый - это шебанг, второй пытается сменить каталог, но сбивает с толку ${0%/*}.

Не могли бы вы объяснить мне эту вторую строку?


2
Как объяснил Андреа в ответе, $ {0% / *} преобразуется в путь к каталогу с префиксом имени скрипта при его вызове. В качестве альтернативы можно использовать встроенную dirnameкоманду как$(dirname $0)
alwayslearning

@alwayslearning: Какую версию оболочки и оболочки вы используете, которая dirnameвстроена? Это, конечно, не в Bash v4.3.11, который является оболочкой по умолчанию в Ubuntu Trusty.
Дэвид Фёрстер

Мои извинения за путаницу, только что проверил, что dirnameэто не встроенная оболочка.
всегда учиться

Ответы:


27

${0}это первый аргумент скрипта, то есть имя скрипта или путь. Если запустить сценарий как path/to/script.sh, то ${0}будет именно эта строка: path/to/script.sh.

%/*Часть изменяет значение ${0}. Это означает: взять все символы, пока не /последует имя файла. В приведенном выше примере ${0%/*}будет path/to.

Вы можете увидеть это в действии на вашей оболочке:

$ x=path/to/script.sh
$ echo "${x%/*}"
path/to

Sh поддерживает много других видов «подстановки параметров». Вот, например, как взять имя файла вместо пути:

$ echo "${x##*/}"
script.sh

В общем, %и %%полосовые суффиксы, а #и ##полосовые префиксы. Вы можете прочитать больше о замене параметров .


2
Этот «|| выход 1» кажется ненужным: будет ли сейчас менять dir $? равно 1.
Йозеф Климук

2
Было бы хорошо упомянуть, что конструкция документирована как «Удалить соответствующий шаблон префикса / суффикса» в руководстве. Также хороший способ запомнить, что # это сдвиг 3 ( слева от $),% это сдвиг 5 ( справа от $), по крайней мере, на клавиатуре США.
chexum

1
@JosefKlimuk: || exit 1 возможно, это потребуется, поскольку cdпри ошибке может завершиться со статусом 2, а не 1. Однако я согласен, что это не очень полезно (обычно программы не заботятся о конкретных статусах выхода). Возможно, это часть более крупного сценария?
Андреа Корбеллини

1
@AndreaCorbellini Конечно, верно. Практически единственный способ, которым он может быть полезен, - это часть большого скрипта. Сценарий, который просто изменяет текущий каталог, не имеет никакого эффекта, потому что он влияет только на оболочку, выполняющую этот сценарий. Родительский процесс никогда не видит это.
HVd
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.