Получение отрицательного результата на тесте для ДОМАШНИХ каталогов с тильдой ~ расширение

Я получаю странную ошибку, не могу понять, почему.

Тем более, что это работает в одном месте, но не в другом сценарии.

У меня есть его код, который проверяет, существуют ли эти каталоги, и ДОМАШНИЕ каталоги с ~ не работают в этом фрагменте кода:

if [[ ! -d "$valueToTest" ]]; then
    echo 'Failed>>:'$valueToTest;
fi;

Я получаю вывод:

Failed>>:~/.workspace/
Failed>>:~/.ssh
Failed>>:~/.workspace/vim/temp
Failed>>:~/.workspace/vim/backup
Failed>>:~/.workspace/vim
Failed>>:~/test

Как я уже сказал, это происходит ТОЛЬКО с расширением ~ для представления моего ДОМАШНЕГО каталога.

И это ЕДИНСТВЕННОЕ место, где это происходит, поскольку у меня есть ДРУГОЙ код, который проверяет путь с расширением ~, т.е. мой ДОМАШНИЙ каталог с расширением ~, И они работают нормально!

Каталоги считываются из значения части ассоциативного массива, но я не понимаю, почему это может быть проблемой. Также вы можете видеть, что в выводе нет кавычек или чего-то подобного.

Я пробовал с двойными кавычками и без них - не повезло.

As in:

$valueToTest
${valueToTest}
"${valueToTest}"

Спасибо за помощь.


person mono-dr    schedule 21.08.2014    source источник
comment
Вот мой ответ, как и просили. Удачи.   -  person konsolebox    schedule 27.08.2014


Ответы (1)


расширение тильды не происходит, когда ~ цитируется в любом путь. И в отличие от пути или расширения имени файла, ~ также не не расширяться, когда он является частью переменной.

Если $valueToTest равно ~/.workspace/, все эти формы не будут работать:

[[ ! -d "$valueToTest" ]]
[[ ! -d $valueToTest ]]
[ ! -d $valueToTest ]

И просто синоним:

test ! -d '~/.workspace/'

Но это сработает:

test ! -d ~/.workspace/

Or

test ! -d /home/user/.workspace/

Таким образом, исправление вашего кода заключается в том, что вместо этого вы должны назначить расширенный путь к своей переменной, а не нерасширенную форму:

valueToTest=~/.workspace/    ## Correct assignment.
valueToTest=~'/.workspace/'  ## Correct assignment.
valueToTest=~"/.workspace/"  ## Correct assignment.

valueToTest='~/.workspace/'  ## Incorrect assignment.
valueToTest="~/.workspace/"  ## Incorrect assignment.

set -- ~/.workspace/         ## Correct assignment.
valueToTest=$1               ## (simulates bash script.sh ~/.workspace/)

set -- "~/.workspace/"       ## Incorrect assignment.
valueToTest=$1

Взлом

Если неизбежно сохраняется только нераскрытая форма, вы можете использовать printf %q и eval для расширения строки. Пока я нахожу достаточно хорошим и безопасным:

printf -v temp %q "$valueToTest"
eval "valueToTest=$temp"

Затем проверьте $valueToTest так, как делаете вы.

Обновлять

В Bash 4.3 printf %q уже будет заключать в кавычки символы тильды (~). Чтобы исправить это, вы можете снова сделать эти символы без кавычек:

printf -v temp %q "$valueToTest"
temp=${temp//\\\~/\~}
eval "valueToTest=$temp"

Вы также можете разрешить $HOME расширяться:

printf -v temp %q "$valueToTest"
temp=${temp//\\\~/\~}
temp=${temp//\\\$HOME/\$HOME}
eval "valueToTest=$temp"

Другое возможное исправление также состоит в том, чтобы просто преобразовать их напрямую:

valueToTest=${valueToTest//\~/$HOME}
valueToTest=${valueToTest//\$HOME/$HOME}
person konsolebox    schedule 27.08.2014
comment
konsolebox - у меня это не сработало: printf -v valueTemp %q $valueToTest; eval valueToTest=$valueTemp;; Я также пытался назначить из связанного массива, потому что в другой части моего кода это работает: ls -al ${gA_SysLocalPATH[HOME/.ssh]}. - person mono-dr; 27.08.2014
comment
Только когда я загружаю эти массивы из файла, эти тесты не работают. Однако, если я назначу напрямую, в коде bash, как в ${gA_SysLocalPATH[HOME/.ssh]}=~/.ssh, они, кажется, работают. - person mono-dr; 27.08.2014
comment
konsolebox - при чтении из файла я даже попробовал ваш код перед назначением в массив, который я тестирую позже (как указано выше), сразу после того, как я прочитал значение из файла. Только когда я читаю эти значения из файла, у меня возникает эта проблема. - person mono-dr; 27.08.2014
comment
@mono-dr Вы должны запустить свой скрипт с помощью -x, например. bash -x script.sh и обновите свой вопрос с его выводом. - person konsolebox; 27.08.2014
comment
Мой скрипт является частью .bash_aliases. Я написал это как функцию, которая вызывается .bash_aliases (в другом файле). Я попытался вызвать функцию, используя -x, как указано выше, но не смог. Есть ли способ вызвать эту функцию, как указано выше, без перемещения ее в новый файл? А также я попытался заменить ~ на $HOME и назначить его как keyValue=$value, чтобы $HOME в $value расширялся, но это тоже не сработало. Спасибо. - person mono-dr; 29.08.2014
comment
@mono-dr Помимо работы с -x, вы также можете добавить set -x перед исполняемым кодом. Пожалуйста, покажите весь свой код в этом файле .bash_aliases, а также команды, которые вы используете для запуска функции, спасибо. Все сообщения, включая подсказки при запуске кода, также будут полезны. Опубликуйте их, обновив свой пост. - person konsolebox; 30.08.2014
comment
Было сложно добавить все сюда в оригинальные вопросы. Поэтому я подготовил GoogleDoc, который вы можете просмотреть здесь: tinyurl.com/MDR-BASH-StackOverflow-01 . Будет ли это работать. Я могу дать права на редактирование всем, если вы хотите добавить в него. Надеюсь, это работает для вас? Благодарю вас! - person mono-dr; 03.09.2014
comment
@mono-dr Я не могу скопировать ваш код для тестирования. Вы можете загрузить его на pastebin.com? - person konsolebox; 03.09.2014
comment
Будет делать так. Я минимизирую и выделяю только проблемы, с которыми я сталкиваюсь. Очень признателен. - person mono-dr; 04.09.2014
comment
Отправь это. Пожалуйста, дайте мне знать, если вы получили электронное письмо с 2 прикрепленными файлами. Благодарю вас! - person mono-dr; 05.09.2014
comment
@mono-dr Думаю, ты Bash 4.3. Пожалуйста, смотрите мое обновление. - person konsolebox; 05.09.2014
comment
Спасибо, что так быстро вернулись. Я это попробую. Так стоит ли об этом говорить разработчикам bash? Поэтому я попробую ваши последние 2 строки (чтобы преобразовать напрямую). Это должно работать, даже если в строке нет ~ или $HOME? - person mono-dr; 05.09.2014
comment
@mono-dr Ожидается, что это сработает, даже если в строке нет ~ или $HOME. Я также думаю, что ~ в кавычках уместно, поэтому поведение Bash 4.3 правильное. Не нужно рассказывать об этом разработчикам bash. - person konsolebox; 05.09.2014
comment
Поможет ли это манипулировать входным файлом ASSOC_ARRAYS, чтобы ~ заключался в кавычки? означает всю строку или просто ~ как в '~'/.workspace? или '$ HOME'/.workspace? Если это решит проблему, то я бы предпочел попробовать это? Или всю строку нужно заключать в кавычки - одинарные или двойные? Я попробую это в ближайшее время. - person mono-dr; 05.09.2014
comment
Потрясающий! Я реализовал это сразу, когда присвоил значение ключу в операторе case в PROCESS.LINE. Большое спасибо! - person mono-dr; 06.09.2014