Запуск скрипта bash по символической ссылке. Как изменить каталог, чтобы работали относительные каталоги

Я использую этот прием:

options=("First option" "Second option" "Quit")
PS3="So what? "
select opt in "${options[@]}"
do
    case $opt in
        "First option")
            echo "First option"
            ;;
        "Second option")
            echo "Second option"    
            ;;
        "Quit")
            echo "We are done..."
            break
            ;;
        *) 
            PS3="" # this hides the prompt
            echo asdf | select foo in "${options[@]}"; do break; done # dummy select 
            PS3="So what? " # this displays the common prompt
            ;;
    esac
done
2
04.10.2020, 12:40
1 ответ

Проблема не связана с символической ссылкой.

Если mycommand.shвызывает ./mycommand2.sh, он ожидает, что его текущий рабочий каталог будет somedir.Текущий рабочий каталог не связан с тем, как команда была названа или вызвана. Это свойство процессов, которое задается системным вызовом chdir()или встроенной командой cdв оболочках.

Если бы вы это сделали:

cd /path/to/somedir
mycommand

mycommand, он же mycommand.sh, все равно найдет ./mycommand2.shв текущем каталоге.

Чтобы mycommand.shнаходил mycommand2.shнезависимо от рабочего каталога, из которого он вызывается, его необходимо изменить, например:

#! /bin/sh -
mydir=$(dirname -- "$0")
"${mydir%/}/mycommand2.sh"

Или, если mycommand.shтребует, чтобы его рабочий каталог былsomedir:

#! /bin/sh -
mydir=$(dirname -- "$0")
CDPATH= cd -P -- "$mydir" || exit

./mycommand2.sh

И это при использовании символической ссылки может вызвать проблемы, как если бы mycommand, dirname -- "$0"вернуло бы имя каталога символической ссылки mycommand, а не скрипта mycommand.sh.

Чтобы обойти это, вы должны изменить mycommand.shкак:

#! /bin/sh -
mydir=$(dirname -- "$(readlink -f -- "$0")")
"${mydir%/}/mycommand2.sh"

Гдеreadlink -f(не стандартная команда, а довольно распространенная )разрешит все символические ссылки. Это предполагает, что mycommand.shсам по себе не является символической ссылкой на скрипт в другом каталоге.

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

#! /bin/sh -
cd /path/to/somedir &&
  exec./mycommand.sh "$@"
2
18.03.2021, 23:00

Теги

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