Что делает $ {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.