Расширение Тильды в кавычках
Я пишу сценарий, где должен найти некоторые файлы в пользовательском каталоге, который может содержать тильду (таким образом, возможно иметь user_defined_directory='~/foo'
). Конструкция выглядит
found_files=$(find "$user_defined_directory" -type f … )
Я использую кавычки для покрытия возможных пробелов в этом пути, но расширение тильды не работает в кавычках в соответствии с man-страницей. Я знаю :
оператор, возможно, может сделать это расширение, но я не могу понять, как его использовать здесь.
«Пользовательский каталог» берется из другого файла конфигурации в каталоге пользователя $ HOME. Он не переходит к моему скрипту в качестве параметра, он анализируется из этой другой конфигурации в написанном скрипте.
- grep для выражения, содержащего переменную
- Как сохранить строки в строке в Bash?
- Переменные оболочки, находящиеся внутри цикла, не видны вне его
- Сохранение текущего каталога в историю bash
- Backticks против брекетов в Bash
- Проверка успеха команды в команде bash `if `
- Как циклически перебирать каталог для удаления файлов с определенными расширениями
- Bash расширяет переменную переменной
- Как удалить весь текст после символа в bash?
- Как предотвратить появление команд в истории bash?
- Ошибка скрипта Bash [:! =: Ожидаемый унарный оператор
- Почему ls дает разные выходные данные при передаче по трубопроводам
- Как удалить файлы старше X часов
Вы можете использовать "${user_defined_directory/#~/$HOME}"
чтобы заменить «~» в начале строки домашним каталогом текущего пользователя. Обратите внимание, что это не будет обрабатывать формат ~username/subdir
, только простой ~
. Если вам нужно обрабатывать более сложные версии, вам нужно будет написать гораздо более сложный конвертер.
Это работает с некоторыми довольно правдоподобными предположениями, но это далеко не очевидный код (и не является однострочным):
# Working function - painful, but can you simplify any of it? # NB: Assumes that ~user does not expand to a name with double spaces or # tabs or newlines, etc. expand_tilde() { case "$1" in (\~) echo "$HOME";; (\~/*) echo "$HOME/${1#\~/}";; (\~[^/]*/*) local user=$(eval echo ${1%%/*}) echo "$user/${1#*/}";; (\~[^/]*) eval echo ${1};; (*) echo "$1";; esac } # Test cases name1="~/Documents/over enthusiastic" name2="~crl/Documents/double spaced" name3="/work/whiffle/two spaces are better than one" expand_tilde "$name1" expand_tilde "$name2" expand_tilde "$name3" expand_tilde "~" expand_tilde "~/" expand_tilde "~crl" expand_tilde "~crl/" # This is illustrative of the 'normal use' of expand_tilde function x=$(expand_tilde "$name1") echo "x=[$x]"
При запуске на моей машине (где есть пользователь crl
), выход:
/Users/jleffler/Documents/over enthusiastic /Users/crl/Documents/double spaced /work/whiffle/two spaces are better than one /Users/jleffler /Users/jleffler/ /Users/crl /Users/crl/ x=[/Users/jleffler/Documents/over enthusiastic]
Функция tilde_expansion
имеет дело с различными случаями отдельно и по-разному. Первое предложение имеет значение ~
и просто заменяет $HOME
. Второй случай паранойи: ~/
отображается в $HOME/
. Третий имеет дело с ~/anything
(включая пустое «все»). Следующий случай касается ~user
. «Уловка все» имеет дело со всем остальным.
Обратите внимание, что код делает (правдоподобное) предположение, что ~user
не будет расширяться до значения, содержащего любые двойные пробелы, а также никаких вкладок или новых строк (и, возможно, других пространственно-подобных символов). Если вам придется иметь дело с этим, жизнь будет адом.
Обратите внимание на ответ chdir()
на домашний каталог , в котором объясняется, что POSIX требует ~
для расширения до текущего значения $HOME
, но ~user
расширяет значение исходного каталога из базы данных паролей.
Тильда определенно не расширяется внутри цитаты. Возможно, есть и другой трюк, но я делаю в этой ситуации следующее:
find ~/"$user_defined_directory" -type f
т.е. переместить стартовые ~/
внешние кавычки и сохранить остальную часть пути в кавычках.