2013-08-24 2 views
2

Каков наилучший способ написать сценарий оболочки, который будет обращаться к файлам по отношению к нему, чтобы не иметь значения, откуда я его вызываю? «Легкий» означает самый простой/рекомендуемый способ, который будет работать в разных системах/оболочках.Создание сценариев оболочки, надежных по отношению к местоположению, из которого они вызваны от

Пример

Скажем, у меня есть папка ~/MyProject с подпапок scripts/ и files/. В scripts/, у меня есть скрипт foo.sh, который хочет получить доступ к файлам в files/:

if [ -f "../files/somefile.ext" ]; then 
    echo "File found" 
else 
    echo "File not found" 
fi 

Это будет работать хорошо, если я cd ~/MyProject/scripts && ./foo.sh, но он потерпит неудачу с cd ~/MyProject && scripts/foo.sh.

+1

См. если http://stackoverflow.com/questions/59895/can-a-bash-script-tell-what-directory-its-stored-in помогает. –

ответ

0

Не уверен, что это достаточно легко для вас, но это может дать вам решение:

Shell Script Loader

+0

Я бы предпочел не устанавливать дополнительные вещи. Я чувствую, что должно быть довольно простым писать сценарии оболочки, которые можно вызывать из любого места, но, возможно, это просто неправильно. –

+0

@ IngoBürk Ну, это зависит от вас :) Я сделал проект в конце концов из-за этой необходимости. Если бы снаряды предоставили такое решение, это уже не было бы необходимо. Вы могли бы сделать встроенное решение по своему усмотрению, аналогично тому, что у меня было, но я бы поспорил, что сложность будет просто схожей, если вы не предпочтете вместо этого использовать хаки, что в большинстве случаев заставляет сценарий работать очень медленно из-за многих вызовы подзаголовков и вызов внешних команд. Иногда это также делает скрипт более запутанным в отношении читаемости. Кстати, это сценарии тоже на всякий случай, если вы не знаете. – konsolebox

1

сделать все пути абсолютной. Используйте переменные окружения, когда это возможно, например $ HOME. Вы столкнулись с слабостью сценариев UNIX.

Используя .profile или .bash_profile, ваши разработчики могут установить множество переменных ENV. Тогда ваши скрипты могут использовать эти переменные.

В одном из мест, где я работал, вы можете запустить скрипт, который подскажет вам, для какой версии вы хотите посмотреть, и установите ENV таким образом, чтобы взаимодействие с разработчиком было довольно простым.

+0

Скажите, что это скрипт в git repo. Любой, кто клонирует его, будет иметь его в другой папке - как я узнаю какие-либо абсолютные пути? –

+0

@Ingo: но как бы скрипт знал? Просто сделайте рабочий путь входным параметром. – Vlad

+0

«Как бы скрипт знал?» - Я точно хочу :) Я бы хотел, чтобы в сценариях была только опция, чтобы система рассматривала ее так, как если бы она была вызвана из каталога, в котором она находится ... –

3

Вы можете обычно сделать:

mydir="$(dirname $0)" 

получить каталог запущенного сценария.

Тогда просто используйте это, чтобы найти ваши файлы.

+0

Так я знал до сих пор. Но другие потоки на SO предполагают, что во многих случаях это прерывается (может быть, это разные системы или разные способы вызова сценария, например, поиск его). –

+0

Редактировать вопрос, чтобы добавить дать такие примеры. В настоящее время ваш вопрос слишком расплывчатый. (По крайней мере, вы должны ограничить использование в некоторой степени. Слишком большая общность не может ничего сделать.) –

0
if [ -f "../files/somefile.ext"] 
then 
    echo "file was found" 
else 
    echo "file was not found" 
fi 

второй:

if [ ! -f /tmp/foo.txt ]; then 
    echo "File not found!" 
fi 
+0

... что? Я не знаю, что вы пытаетесь мне сказать, извините. –

0

Учитывая, что $0 должен содержать путь к исполняемому скрипту, вы можете просто перейдите в него, а затем процесс обычно

Таким образом, вы просто сделать

scriptDir=$(dirname -- "$0") 
cd -- "$scriptDir" 

Но это все еще хак, вы, вероятно, должны подумать о способе работы с абсолютным пути

0

К сожалению, похоже, что не существует действительно общего решения. Моя личная рекомендация (и практика) заключается в том, чтобы писать только для оболочек, которые обеспечивают постоянный доступ к этому - последние ${.sh.file}, bash$BASH_SOURCE и т. Д. (Я не знаю решение zsh, но я уверен, что там является одним.)

Помимо этого, лучшим решением является предотвращение проблемы в некотором роде; например, для вашего примера сценария в репозитории git, вы можете потребовать, чтобы сценарий вызывался из того каталога, в котором он находится.После проверки того, что, проверив [[ -e myscript ]], вы можете ожидать, что относительные ссылки будут работать должным образом. (Да, для полной надежности, вам нужно будет жестко указать базовое имя сценария в тест, по той же причине, что проблема существует в первую очередь - она ​​доступна для оболочки во всех возможных обстоятельствах.)

Смежные вопросы