2016-09-17 3 views
1

Это мое первое время, когда-то делаю что-то с bash-программированием. В качестве первого примера я пытаюсь установить свой .bashrc из моего .bash_profile - даже когда ~/.bashrc является символической ссылкой.

.bash_profile:

if [ -f ~/.bashrc ] && ! [ -L ~/.bashrc ] 
then 
    # ~/.bashrc is a regular file. Source it! 
    source ~/.bashrc 
    echo "~/.bashrc found." 
elif [ -L ~/.bashrc ] 
then 
    # ~/.bashrc is a symbolic link. 

    # Recursivly follow symbolic links. 
    location="~/.bashrc" 
    while [ -L $location ] 
    do 
    # QUESTION: Control-Flow never reaches this point. 

    # Follow link on macOS. 
    location="$(readlink $path)" 
    done 

    # Check if final target is regular file. Source it! 
    if [ -f $location ] 
    then 
    source $location 
    echo "Symlink to .bashrc found." 
    fi 
else 
    echo "No valid .bashrc found." 
fi 

Это то, что я ожидал мой код, чтобы сделать:

  • Если ~/.bashrc не является символической ссылкой, но обычный файл: Источник он.
  • В противном случае, если ~/.bashrc является символической ссылкой:
    • Следуйте символическую ссылку, пока цель продолжает быть символической ссылкой.
    • Если конечная цель является обычным файлом: Источник:.
  • В противном случае: Оставить заявку.

В качестве теста я создал символическую ссылку ~/.bashrc в исходный файл .dotfiles/.bashrc. Мой код входит в elif, как и предполагалось, но, к сожалению, никогда не входит в тело while -loop (как и следовало ожидать, поскольку ~/.bashrc является символической ссылкой).

Что здесь происходит? Я думаю, что присвоение переменной location ошибочно.

+0

В будущем попытайтесь сломать свои вопросы, чтобы включить только определенную часть вашего кода, которая не делает то, что вы хотите. Здесь много, что не имеет никакого отношения к актуальной проблеме; см. http://stackoverflow.com/help/mcve. (Если вы не были ясны *, где * проблема, использование 'bash -x' для запуска чего-то с каждой командой, зарегистрированной для того, чтобы увидеть, что вещи сначала идут не так, поможет уменьшить это). –

+0

BTW, также запустите свой код через http://shellcheck.net/ и исправьте, что он найдет - прямо сейчас у него есть куча тонких ошибок из-за неадекватного цитирования, которое станет очевидным, если у вас когда-либо был домашний каталог, имя включало любые символы в 'IFS'. –

ответ

2

Заменить:

location="$(readlink $path)" 

С:

location="$(readlink $location)" 

Примечания: не

  1. Переменная path никогда не была определена. Я считаю, что вы намеревались применить readlink к location вместо

  2. Если у вас GNU readlink (доступна на Linux, самогон и т.д.), то опция -f может использоваться отпадает необходимость в цикле.

  3. В общем, переменные оболочки следует ссылаться в двойные кавычки, если один не хочет оболочка применить слово расщепления, тильды и расширение имени пути к значению переменной.

    Например, в следующей строке мы хотим Расширение тильды.Таким образом, ~/ потребности быть вне кавычек:

    location=~/.bashrc 
    

    После того, как это делается, части сценария, где location ссылается должны быть в двойных кавычках. В качестве примера:

    location="$(readlink "$location")" 
    

    Это очень важно, например, если имена файлов или путей содержат пробелы.

+0

Я думаю, что я могу получить «coreutils» через домашнее пиво. – Herickson

+1

Он работает, кстати. Большое вам спасибо! – Herickson

+0

Зачем нужны дополнительные скобки при назначении местоположения? – Herickson

2

Это вызывает проблему:

location="~/.bashrc" 

Тильда расширение не происходит в двойных кавычках, и это не произойдет в

[ -L $location ] 

либо.

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

location="$HOME/.bashrc" 

или аналогичный.