Эквивалент% ~ dp0 в sh

Я конвертирую некоторые пакетные файлы Windows в сценарии Unix, используя sh. У меня проблемы, потому что какое-то поведение зависит от макроса% ~ dp0, доступного в пакетных файлах.

Есть ли какой-либо sh эквивалент этого? Любой способ получить каталог, в котором живет исполняемый script?

Ответы

Ответ 1

Проблема (для вас) с $0 заключается в том, что она настроена на использование какой-либо командной строки для вызова script, а не местоположения самого script. Это может затруднить получение полного пути каталога, содержащего script, который вы получаете из %~dp0 в пакетном файле Windows.

Например, рассмотрим следующие script, dollar.sh:

#!/bin/bash
echo $0

Если вы запустите его, вы получите следующий результат:

# ./dollar.sh
./dollar.sh
# /tmp/dollar.sh
/tmp/dollar.sh

Итак, чтобы получить полное имя каталога script, я делаю следующее:

cd `dirname $0`
SCRIPTDIR=`pwd`
cd -

Это работает следующим образом:

  • cd в каталог script, используя либо относительный, либо абсолютный путь из командной строки.
  • Получает абсолютный путь этого каталога и сохраняет его в SCRIPTDIR.
  • Возврат к предыдущему рабочему каталогу с помощью "cd -".

Ответ 2

Я пытался найти путь для script, который был получен из другого script. И это была моя проблема, когда поиск текста просто копируется в вызывающий script, поэтому $0 всегда возвращает информацию о вызывающем script.

Я нашел обходной путь, который работает только в bash, $BASH_SOURCE всегда имеет информацию о script, в которой он упоминается. Даже если источник script найден правильно, он корректно разрешен исходным (sourced) script.

Ответ 3

В bash под Linux вы можете получить полный путь к команде с помощью:

readlink /proc/$$/fd/255

и получить каталог:

dir=$(dirname $(readlink /proc/$$/fd/255))

Это уродливо, но мне еще предстоит найти другой способ.

Ответ 4

Да, вы можете! Это в аргументах.:)

посмотрите

${0}

комбинируя это с

{$var%Pattern}
Remove from $var  the shortest part of $Pattern that matches the back end of $var.

что вы хотите, просто

${0%/*}

Я рекомендую Расширенный Bash Руководство по разработке сценариев. (то есть также, где указанная выше информация). Специально для части Преобразование файлов DOS в файлы сценариев командной оболочки может быть вам полезна.:)

Если я вас неправильно понял, вам, возможно, придется объединить это с выходом "pwd". Поскольку он содержит только путь, с которым вызывался script с! Попробуйте выполнить script:

#!/bin/bash
called_path=${0%/*}
stripped=${called_path#[^/]*}
real_path=`pwd`$stripped
echo "called path: $called_path"
echo "stripped: $stripped"
echo "pwd: `pwd`"
echo "real path: $real_path

Это требует некоторой работы. Я рекомендую использовать подход Дейва Уэбба, если это невозможно.

Ответ 5

Правильный ответ таков: Как определить местоположение моего script? Я хочу прочитать некоторые файлы конфигурации из того же места.

Важно понимать, что в общем случае эта проблема не имеет решения. Любой подход, о котором вы, возможно, слышали, и любой подход, который будет подробно описан ниже, имеет недостатки и будет работать только в конкретных случаях. Прежде всего, постарайтесь полностью избежать проблемы, не завися от расположения вашего script!

Прежде чем погрузиться в решения, позвольте прояснить некоторые недоразумения. Важно понимать, что: Ваш script фактически не имеет местоположения! Везде, где байты заканчиваются, для него нет "одного канонического пути". Никогда. $0 НЕ является ответом на вашу проблему. Если вы так думаете, вы можете либо перестать читать, либо писать больше ошибок, либо можете принять это и прочитать дальше....

Ответ 6

Я пробовал $0 раньше, а именно:

dirname $0

и он просто возвращает "." даже когда script используется другим script:

.../somedir/somescript.sh

Ответ 7

Это должно работать для оболочки bash:

dir=$(dirname $(readlink -m $BASH_SOURCE))

Тест script:

#!/bin/bash
echo $(dirname $(readlink -m $BASH_SOURCE))

Тест на запуск:

$ ./somedir/test.sh 
/tmp/somedir
$ source ./somedir/test.sh 
/tmp/somedir
$ bash ./somedir/test.sh 
/tmp/somedir
$ . ./somedir/test.sh 
/tmp/somedir

Ответ 8

Попробуйте следующее:

${0%/*}