Чому я не можу записатись на цитований тильд ('~')?


32

Написання мого першого сценарію, тому я впевнений, що це основне питання, але чи можу я хтось пояснити мені, чому я можу:

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

Але не

cd '~'
cd '~/bin'

Мені потрібно до cdкаталогу доріжок із пробілом в одному з імен каталогів, тому мені потрібні лапки (це Windows Program Filesпід вином). Я можу обійти його двома cdкомандами, але чому я не можу ставити ~лапки?

Якщо я набираю cd '~'(або cd "~"), я отримую:

bash: cd: ~: No such file or directory

29
Задайте собі запитання: якщо не вийшло так, як би ви cdперейшли до каталогу з ім'ям ~?
Йорг W Міттаг

2
З іншого боку, якщо ви пишете сценарій, вам слід скористатися абсолютними шляхами та уникати всіх cd. Використовуйте змінні для зберігання імен шляхів, які ви не хочете вводити кілька разів, наприкладpf=~/.wine/drive_c/Program\ Files/; cp /path/to/file "$pf"
десерт

8
@jamesqf: Чому розумна система припускає, що краще за мене знає, що я хочу назвати своїми файлами та каталогами? Крім того, я ніколи не розумів, чому Unix пішов з магічною вбудовою сигналізацією розділювачів компонентів шляху та термінаторів шляху. Що не так з файлом / каталогом з іменем /або NUL?
Йорг W Міттаг

3
@ JörgWMittag імовірноcd ./~
k_g

2
@jamesqf Просто зауважимо, що історично файлові системи Unix дозволяли використовувати будь-яку таблицю у назві файлу, за винятком '/' (роздільник шляху) та '\ 0' (NUL - рядок завершення рядків) - як зазначає Jorg. Інших обмежень немає. Реалізацій файлової системи Unix було багато, тому введення обмежень у будь-яку з них порушило б сумісність та збільшило б її складність - і було б сприйнято як "дивне"! І розширення '~' було введене лише порівняно недавно в csh і більш широко в bash, файли / dirs з '~' символами в невідомі (наприклад, myfile ~ як резервна копія для myfile).
SusanW

Відповіді:


78

Як зазначав @karel у своїй відповіді, ~це особливий персонаж і розгорнутий Bash у домашній каталог поточного користувача. Дивіться посібник Баша на тему "Розширення Тільди" або шукайте заголовок "Розширення Тільди" на сторінці "man" ( man bash).

Будь-яка цитата навколо ~перешкоджає розширенню тильда.


Щоб відповісти на ваше запитання про те, як ви все ще можете використовувати його cdв каталозі з пробілами в його імені, є кілька варіантів:

  • Опустіть котирування та замініть пробіли за допомогою зворотних нахилів:

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

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

    Як бачите, ви можете об'єднати цитовані та не цитовані рядки в Bash, просто записавши їх поруч, не маючи пробілів між ними.

  • Використовуйте змінну середовища $HOMEзамість тильди, яка все ще розширюється всередині "подвійних лапок" (але не "одинарних лапок"):

    cd "$HOME/foo/spaces are cool/bar"

3
@rexkogitans ~'/...'не буде працювати, і це не те, що ця відповідь має. ~/'...'або ~/"..."буде працювати.
hvd

tld; dr: тому що синтаксис оболонки
Сергій Колодяжний

@hvd дякую. Виправлена ​​помилка. Це найповніша відповідь, а також пояснює, як вирішити те, що хоче зробити ОП. ~/'path'це шлях.
rexkogitans

1
@hvd просто мало цікавості, чому б не ~'/...'працювати? Штрих не є особливим символом, тому, здається, він повинен працювати як усередині, так і зовні лапок.
Кодос Джонсон

6
@KodosJohnson Перегляньте розділ сторінки Баша про "Розширення Тільди". Відповідний абзац цього пункту також цитується у відповіді десерту нижче. TL; DR: Розширення Tilde має місце, якщо перший символ у слові є тильдом без котирування, тоді все між цим тильдом та наступним котируючим косою рисою вважається "префіксом тильди". Якщо цей префікс не є дійсною річчю, як +, -, число чи ім'я користувача (цитати там також заборонені), розширення не вдається, і ви отримаєте буквальний символ.
Байт-командир

17

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


~не є псевдонімом у тому сенсі, який bashвін інтерпретує: Псевдоніми дозволяють замінити рядок на слово, коли воно використовується як перше слово простої команди. . Як я пояснюю у своїй відповіді нижче, це скоріше розширення.
десерт

15

Це bashфункція під назвою Tilde Expansion . Цитуючи 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 Expansion має ще кілька цікавих особливостей, наприклад:

  • ~+розширюється до значення PWD, тобто поточного робочого каталогу
  • ~-розширюється до значення OLDPWD, тобто попереднього робочого каталогу
  • ~john розширюється на домашній каталог, пов’язаний з іменем входу "john"

Між іншим, нормально також «перекотувати» з накидами; наприклад, $ touch a; cd \a. (Я думав, що це може зіткнутися з проблемою cd \n, але експерименти принаймні на моїй версії bashпередбачають, що це працює добре.)
LSpice

1

Дослідіть за допомогою echoкоманди

Найпростіший спосіб вивчення того, як все працює в баші, - це echoкоманда. У разі ~використання цього:

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

Як бачимо, коли ви однозначно використовуєте або використовуєте подвійні лапки навколо, ~вона трактується буквально як рядок, а не розширюється як змінна. При використанні зворотних посилань (`) він виконується як команда і генерує повідомлення про помилку.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.