Что такое переносимый способ для (zsh) сценария определить его абсолютный путь?
В Linux я использую что-то вроде
mypath=$(readlink -f $0)
... но это не портативно. (Например, readlink
Дарвин не распознает -f
флаг и не имеет никакого эквивалента.) (Кроме того, использование readlink
для этого, по общему признанию, довольно темного хака.)
Какой способ более портативный?
Ответы:
С
zsh
, это просто:Теперь для других оболочек, хотя
realpath()
иreadlink()
являются стандартными функциями (последний является системным вызовом),realpath
иreadlink
они не являются стандартной командой, хотя некоторые системы имеют одну или другую или обе с различным поведением и набором функций.Как часто, для переносимости, вы можете прибегнуть к
perl
:Это будет вести себя больше как GNU,
readlink -f
чемrealpath()
(GNUreadlink -e
) в том смысле, что он не будет жаловаться, если файл не существует, пока существует его dirname.источник
.zshrc
: см. Этот пост .В Zsh вы можете сделать следующее:
Или, чтобы получить каталог, в котором находится скрипт:
Источник: страница руководства zshexpn (1), раздел РАСШИРЕНИЕ ИСТОРИИ, подраздел Модификаторы (или просто
info -f zsh -n Modifiers
).источник
readlink -f
будет лучше$0:A
.Я использую это в течение нескольких лет:
источник
readlink -f
это когда сам скрипт является символической ссылкой.zsh
, если я выполняю это либо напрямую, либо в подоболочке (как предложено), находясь в моем домашнем каталоге dir (/home/ville
), он печатается/home/ville/zsh
.Этот синтаксис должен быть переносимым на любой интерпретатор в стиле оболочки Bourne (проверено с
bash
,ksh88
,ksh93
,zsh
,mksh
,dash
иbusybox sh
):Эта версия добавляет совместимость с устаревшей оболочкой AT & T Bourne (не POSIX):
источник
$PWD
может быть излишним - вы можете просто установить его на абсолютный ток, какcd -P .
. Я сомневаюсь, что это сработает в bourneshell - но оно должно работать во всех тестах, которые вы тестировали в первый раз. все равно для меняzsh
иdirname
быстро отозвал свой комментарий ...Предполагая, что вы действительно имели в виду абсолютный путь, то есть путь от корневого каталога:
Кстати, это работает в любой оболочке в стиле Bourne.
Если вы имели в виду путь со всеми символическими ссылками, то это другое дело.
readlink -f
работает в Linux (исключая некоторые урезанные системы BusyBox), FreeBSD, NetBSD, OpenBSD и Cygwin, но не в OS / X, AIX, HP / UX или Solaris. Если у вас естьreadlink
, вы можете вызвать его в цикле:Если у вас его нет
readlink
, вы можете аппроксимировать егоls -n
, но это работает только в том случае, еслиls
в имени файла не указан какой-либо непечатаемый символ.(Дополнительная информация
z
в том случае, если цель ссылки заканчивается новой строкой, в противном случае подстановка команд сработает.realpath
Кстати, функция не обрабатывает этот случай для имен каталогов.)источник
ls
реализации, которая искажает непечатные символы, когда вывод не идет в терминал.touch Stéphane; LC_ALL=C busybox ls Stéphane | cat
→St??phane
(это если имя в UTF-8, latin1 дает вам один?
). Я думаю, что видел это и на старых коммерческих Unices.busybox
это? согласно git,busybox ls
с 2011 года код не менялся. Мойbusybox ls
- около 2013 года - этого не делает. Это одна - около 2012 - делает . Это может объяснить почему. Вы создали свойbusybox
с поддержкой Unicode - чтобы включить поддержку wchar? Возможно, вы захотите попробовать, либо проверить параметры сборки вmkinitcpio
busybox
пакете.При условии, что у вас есть разрешения на выполнение в текущем каталоге - или в каталоге, из которого вы выполняли свой сценарий оболочки, - если вам нужен абсолютный путь к каталогу, все, что вам нужно
cd
.Шаг 10 из
cd
спецификацииИ на
pwd -P
Это потому, что
cd -P
должен установить текущий рабочий каталог на то, чтоpwd -P
должно печатать иначе, и этоcd -
должно напечатать,$OLDPWD
что работает следующее:ВЫХОД
ждать его...
ВЫХОД
И когда я печатаю с
cd -
я печатаю$OLDPWD
.cd
устанавливает,$PWD
как только яcd -P .
$PWD
теперь абсолютный путь к/
- поэтому мне не нужны никакие другие переменные. И на самом деле, я даже не нужна буксировка ,.
но есть указанное поведение сброса$PWD
в$HOME
в интерактивной оболочке , когдаcd
это прикрасы. Так что это просто хорошая привычка развиваться.Так что простого выполнения вышеупомянутого пути
${0%/*}
должно быть более чем достаточно, чтобы проверить$0
путь, но в случае, если$0
это само по себе мягкая ссылка, вы, к сожалению, не можете изменить каталог на него.Вот функция, которая справится с этим:
Он стремится сделать столько, сколько мог бы в текущей оболочке - не вызывая подоболочку - хотя существуют подоболочки, вызываемые для ошибок и программных ссылок, которые не указывают на каталоги. Это зависит от POSIX-совместимой оболочки и POSIX-совместимой,
ls
а также от чистого_function()
пространства имен. Без последнего он будет работать нормально, хотя в этом случае он может перезаписатьunset
некоторые текущие функции оболочки. В общем, все эти зависимости должны быть достаточно надежно доступны на Unix-машине.Вызывается с аргументами или без них, и первое, что он делает, - возвращается
$PWD
к своему каноническому значению - при необходимости он разрешает любые ссылки в них на свои цели. Называется без аргументов и все тут; но вызывается с ними, и он будет разрешать и канонизировать путь для каждого или распечатать сообщение,stderr
почему бы и нет.Поскольку он в основном работает в текущей оболочке, он должен иметь возможность обрабатывать список аргументов любой длины. Он также ищет
$_zdlm
переменную (которую онunset
также просматривает, когда проходит через нее) и печатает ее C-escape-значение сразу справа от каждого из своих аргументов, за каждым из которых всегда следует также один\n
символ ewline.Он сильно меняет каталог, но, кроме установки его канонического значения, он не влияет
$PWD
, хотя$OLDPWD
на него нельзя рассчитывать, когда он закончится.Он пытается выйти из каждого из своих аргументов как можно скорее. Сначала он пытается
cd
в$1
. Если это возможно, он печатает канонический путь аргумента кstdout
. Если он не может, он проверяет, что$1
существует и не является мягкой ссылкой. Если это правда, он печатает.Таким образом, он обрабатывает любой аргумент типа файла, на который оболочка имеет права доступа, если только
$1
это не символическая ссылка, которая не указывает на каталог. В этом случае он вызываетwhile
цикл в подоболочке.Звонит,
ls
чтобы прочитать ссылку. Текущий каталог должен быть сначала изменен на свое первоначальное значение, чтобы надежно обрабатывать любые референтные пути, и поэтому в подобласти подстановки команд функция делает:Он отбрасывает слева от
ls
выходных данных столько, сколько должен полностью содержать имя ссылки и строку->
. Хотя я сначала пытался избежать этого,shift
и$IFS
оказалось, что это самый надежный метод, насколько я могу судить. Это то же самое, что делает Жиль_Плохая_мани_челка - и это хорошо сделано.Он будет повторять этот процесс в цикле до тех пор, пока возвращаемое имя файла не
ls
станет мягкой ссылкой. В этот момент он канонизирует этот путь, как и раньше, сcd
последующей печатью.Пример использования:
ВЫХОД
Или возможно ...
ВЫХОД
источник
как насчет сочувствующей однострочности, когда есть python для предотвращения переопределения алгоритма?
такой же, как /programming//a/7305217
источник