Почему я не могу перейти на цитируемую тильду ('~')?

33

Написание моего первого сценария, так что я уверен, что это основной вопрос, но может кто-нибудь объяснить мне, почему я могу:

cd ~
cd bin
cd ~/bin
cd 'bin'

Но нет

cd '~'
cd '~/bin'

Мне нужно cdуказать путь к каталогу с пробелом в одном из имен каталогов, поэтому мне нужны кавычки (это винда Program Filesпод вином). Я могу обойти это с помощью двух cdкоманд, но почему я не могу поставить ~в кавычки?

Если я наберу cd '~'(или cd "~") я получу:

bash: cd: ~: No such file or directory
B.Tanner
источник
29
Задайте себе вопрос: если бы это не сработало, как бы вы cdпопали в каталог с именем ~?
Йорг Миттаг,
2
Как примечание: если вы пишете сценарий, вы должны использовать абсолютные пути и избегать всего cd. Используйте переменные для хранения путей, которые вы не хотите вводить несколько раз, напримерpf=~/.wine/drive_c/Program\ Files/; cp /path/to/file "$pf"
десерт
8
@jamesqf: Почему разумная система может лучше меня знать, что я хочу назвать своими файлами и каталогами? Кроме того, я никогда не понимал, почему Unix пошел с волшебной внутриполосной сигнализацией разделителей компонентов пути и ограничителей пути. Что не так с файлом / каталогом с именем /или NUL?
Йорг Миттаг
3
@ JörgWMittag предположительноcd ./~
k_g
2
@jamesqf Просто для того, чтобы отметить, что исторически файловые системы Unix допускали любой символ в имени файла, кроме '/' (разделитель пути) и '\ 0' (NUL - символ окончания строки) - как отмечает Йорг. Других ограничений нет. Было много реализаций файловой системы Unix, поэтому введение ограничений в любой из них нарушило бы совместимость и увеличило бы сложность - и было бы расценено как «странное»! А расширение '~' было введено сравнительно недавно в csh и более широко в bash, файлы / каталоги с символами '~' в не неизвестны (например, myfile ~ как резервная копия для myfile).
СьюзенW,

Ответы:

79

Как отметил @karel в своем ответе, ~это специальный символ, который Bash расширил до домашнего каталога текущего пользователя. См . Руководство Bash по «Расширению тильды» или поищите заголовок «Расширение тильды» на странице руководства ( man bash).

Любая цитата вокруг этого ~препятствует расширению тильды.


Чтобы ответить на ваш вопрос о том, как вы все еще можете использовать его cdв каталоге с пробелами в его имени, есть несколько альтернатив:

  • Опустите кавычки и вместо них используйте пробелы с обратной косой чертой:

    cd ~/foo/spaces\ are\ cool/bar
  • Процитируйте оставшуюся часть пути, но опустите их вокруг тильды и первой косой черты:

    cd ~/"foo/spaces are cool/bar"

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

  • Используйте переменную окружения $HOMEвместо тильды, которая все еще раскрывается внутри «двойных кавычек» (но не «одинарных кавычек»):

    cd "$HOME/foo/spaces are cool/bar"
Byte Commander
источник
3
@rexkogitans ~'/...'не сработает и не соответствует этому ответу. ~/'...'или ~/"..."будет работать.
января
tld; dr: потому что синтаксис оболочки
Сергей Колодяжный
@hvd спасибо. Исправлена ​​опечатка. Это наиболее полный ответ, а также объясняется, как решить, что ОП хочет сделать. ~/'path'это путь
rexkogitans
1
@hvd просто немного любопытства, почему бы не ~'/...'работать? Косая черта не является специальным символом, поэтому, похоже, она должна работать внутри или вне кавычек.
Кодос Джонсон
6
@KodosJohnson Загляните в раздел справки Bash, посвященный «Расширению Тильды». Соответствующий параграф этого также цитируется в ответе десерта ниже. TL; DR: раскрытие тильды происходит, если первый символ в слове является тильдой без кавычек, тогда все, что находится между тильдой и следующей косой чертой без кавычек, считается «префиксом тильды». Если этот префикс недопустим, например, +, -, число или имя пользователя (кавычки там тоже недопустимы), расширение завершится неудачно, и вы получите буквальный символ ~.
Byte Commander
17

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

Карел
источник
~не является псевдонимом в том смысле, в каком bashего интерпретируют: псевдонимы позволяют заменить слово строкой, когда оно используется в качестве первого слова простой команды. , Как я объясняю в своем ответе ниже, это скорее расширение.
десерт
15

Эта bashфункция называется расширением Тильды . Ссылаясь на man bash:

Если слово начинается с символа кавычки без кавычек (`~ '), все символы, предшествующие первой косой черте без кавычек (или все символы, если нет косой черты без кавычек), считаются префиксом тильды. Если ни один из символов в префиксе тильды не заключен в кавычки, символы в префиксе тильды, следующие за тильдой, рассматриваются как возможное имя для входа. Если это имя входа является пустой строкой, тильда заменяется значением параметра оболочки HOME. Если HOME не установлен, вместо него подставляется домашний каталог пользователя, выполняющего оболочку.

Чтобы раскрытие работало, символ тильды ~должен быть заключен в кавычки, иначе символ воспринимается буквально и cdзавершается неудачей, если ~в текущем каталоге нет имени с именем . Смотрите этот интенсивный ответ для объяснения цитирования в bash. Если вам нужно процитировать часть пути, вы можете:

  1. цитируйте как минимум символы, которые нужно заключать в одинарные кавычки, например

    ~/dir' 'with' 'spaces/

    или

    ~/'dir with spaces/'
  2. цитируйте как минимум символы, которые нужно заключить в двойные кавычки, например

    ~/dir" "with" "spaces/

    или

    ~/"dir with spaces/"
  3. цитируйте только те символы, которые нужно заключить в кавычки, например

    ~/dir\ with\ spaces/

Расширение Tilde имеет еще несколько интересных функций, например:

  • ~+расширяется до значения PWD, т.е. текущего рабочего каталога
  • ~-расширяется до значения OLDPWD, т.е. предыдущего рабочего каталога
  • ~john расширяется до домашнего каталога, связанного с логином «Джон»
Десерт
источник
Между прочим, это хорошо, чтобы «перебивать» и обратную косую черту; например, $ touch a; cd \a. (Я думал, что это может столкнуться с проблемами cd \n, но эксперименты, по крайней мере, с моей версией, bashпредполагают, что это работает нормально.)
LSpice
1

Исследуйте используя echoкоманду

Самый простой способ изучения того, как все работает в bash, - это echoкоманда. В случае ~использования это:

$ echo ~
/home/rick
$ echo '~'
~
$ echo "~"
~
$ echo `~`
bash: /home/rick: Is a directory

Как вы можете видеть, когда вы ~заключаете в одинарные кавычки или используете двойные кавычки, они интерпретируются буквально как строка, а не как переменная. Когда вы используете backticks (`), он выполняется как команда и генерирует сообщение об ошибке.

WinEunuuchs2Unix
источник