У меня есть скрипт (~/.../gremlin), для которого я создал мягкую ссылку:
ln -s ~/[...]/gremlin ~/sc/gremlin
~/sc/gremlin
находится в $PATH
.
Вызов скрипта напрямую работает.
Вызов через ссылку — нет.
Он использует dirname $0
, поэтому ничего не получает.
Есть ли способ заставить эту настройку работать, не меняя скрипт и не создавая еще один вместо программной ссылки?
Вот как используется $0:
case `uname` in
CYGWIN*)
CP=$( echo `dirname $0`/../lib/*.jar . | sed 's/ /;/g')
;;
*)
CP=$( echo `dirname $0`/../lib/*.jar . | sed 's/ /:/g')
esac
решение1
Является ли использование dirname $0
проблемой или нет, будет зависеть откакон используется. Без дополнительных подробностей мы не можем ответить на этот вопрос.
Если (а) использование dirname $0
вызывает проблемы и (б) вы не можете изменить скрипт, то решением будет заменить мягкую ссылку ~/sc/gremlin
скриптом:
#!/bin/sh
exec ~/../gremlin "$@"
Таким образом, ~/../gremlin
будет работать с правильным $0
.
Использование exec
означает, что процесс, выполняющий скрипт, ~/../gremlin
заменит процесс, выполняющий ~/sc/gremlin
. Это более эффективно, чем сохранение обоих процессов до ~/../gremlin
завершения.
решение2
Если вы хотите получить ~/...
каталог из $0
, а не ~/sc
из скрипта, вы можете сделать следующее:
Если это zsh
сценарий:
#! /bin/zsh -
dir=$0:A:h
В противном случае, и при условии, что у вас есть readlink
команда, которая ведет себя как команда GNU (в некоторых системах есть realpath
команда, которую вы можете использовать вместо нее):
#! /bin/sh -
dir=$(dirname -- "$(readlink -f -- "$0")")
readlink -f
и $0:A
дать вамканоническийпуть к файлу, то есть абсолютный путь после разрешения всех символических ссылок во всех компонентах пути.
А потом:
set -- "$dir"/../lib/*.jar .
case $(uname) in
CYGWIN*) IFS=';';;
*) IFS=:;;
esac
CP="$*"
Или:
case $(uname) in
CYGWIN*) sep=';';;
*) sep=:;;
esac
CP=$(printf "%s$sep" "$dir"/../lib/*.jar).
решение3
Как отметил @john1024, опечатка в вопросе автора может быть сутью вопроса:
ln -s ~/.../gremlin ~/sc/gremlin
Хотя некоторые приложения учитывают тройные точки, файловые системы Unix этого не делают. Вашоболочкарасширяет ~
(тильду), а не ln
, поэтому
ln -s ~/../gremlin ~/sc/gremlin
расширит имя пути, как и ожидалось. Если ссылка уже существует, вы можете перезаписать ее с помощью параметра -f
. Однако, если целью является реальный файл, -f
параметр молча перезапишет файл символической ссылкой. Вы можете захотеть использовать параметр -i
, который, по крайней мере, скажет вам, что там уже что-то есть.
Если вы хотите проверить ссылку (доказать, что она указывает на файл), полезна -L
опция :ls
ls -lL ~/sc/gremlin
Если это не файл, ls
то (в зависимости от реализации) будет отображаться только символ l
для типа (первый символ в списке) с вопросительными знаками для битов разрешений) или какое-либо другое указание на то, что он не указывает на реальный файл (OSX просто отказывается что-либо показывать в этом случае, хотя и учитывает размер символической ссылки в общем).
Дальнейшее чтение: