Чи вважається тильда `~` відносною стежкою?


35

Я намагаюся витягнути іншу частину інсталятора бібліотеки cuda Nvidia. Я використовую таку команду:

mkdir ~/Downloads/nvidia_installers
./cuda_6.5.14_linux_64.run -extract=~/Downloads/nvidia_installers

І я отримую таке повідомлення:

ERROR: extract: path must be absolute.

І коли я набираю команду з буквальною адресою мого будинку, вона працює чудово.

./cuda_6.5.14_linux_64.run -extract=/home/likewise-open/XXX/username/Downloads/nvidia_installers

Я розгублений, чи не слід ~ бути однаковим з / home / також відкрити / XXX / ім'я користувача?

Перевірено:

./cuda_6.5.14_linux_64.run -extract=$HOME/Downloads/nvidia_installers

і це працює, але я не знаю, чому це не дозволяє ~


2
Пов’язано: "Префікс тильди" складається з символу <tilde> без котирування на початку слова, за яким усі символи передують першому котируванню "
Брайам

Відповіді:


47

Bash розширює лише ~, якщо це початок слова. Ви можете бачити це між такими командами:

$ echo -extract=~/test
-extract=~/test

oli@bert:~$ echo -extract ~/test
-extract /home/oli/test

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

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

$ echo Thisisastring${HOME}awrawr
Thisisastring/home/oliawrawr

Поки ми говоримо про ~це, він насправді має ще пару інших видів заміни:

  • ~+поточний робочий каталог (читати з $PWD)
  • ~-попередній робочий каталог (читати з $OLDPWD)

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

Детальніше про це ви можете прочитати в man bash | less -p ' Tilde'


2
Варто відзначити , що zsh це (або , швидше за , може бути налаштований) розширюватися ~після =теж. Серед інших зручних удосконалень, які він має над басом.
Ян Худек

@JanHudec Ні - це складніше; Йдеться не про розширення після =; йдеться про розширення на початку правого боку pf змінної призначення. Це робить наш випадок трохи більш заплутаним, коли уважно придивіться - дивіться мою відповідь. І zshне відрізняється від bashцього; Опис для 'zsh' є трохи криптовалютним: info --subnodes zsh | less +/'14.7.4 Notes'(сторінки з zsh man відсутні)
Volker Siegel

1
@VolkerSiegel: zshдуже настроюється. У моєму zsh echo -extract=~/testрезультати в -extract=/home/user/test. Це увімкнено MAGIC_EQUAL_SUBSTопціями. Зі сторони, у мене всі сторінки zsh man просто чудові.
Ян Худек

@JanHudec Не сумнівайтеся zshу налаштуваннях та інших удосконаленнях; Я б очікував, що MAGIC_EQUAL_SUBST (описано в 14.7.4) за замовчуванням не встановлено і використовується рідко; Тепер це, очевидно, більш актуально, якщо ввімкнено його. Після того, як я отримаю приклад свого розділу в хорошій формі, це зробить приємне доповнення ...
Volker Siegel,

@JanHudec Щодо сторінок zsh man, вони деякий час були відсутні у пакунках Ubuntu, дякую за підказку, не знав, що це виправлено; Дивлячись на помилку, вона виправлена ​​для утопічного, але не довірливого - це пояснює! ( панель запуску: відсутні всі маніпуляції zsh та вбудовані довідкові файли, а АС: zsh man відсутній ... )
Volker Siegel

19

Просто фіксуючи це

Ця команда показує повідомлення про помилку "ПОМИЛКА: extract: шлях повинен бути абсолютним":

./cuda_6.5.14_linux_64.run -extract=~/Downloads/nvidia_installers

Помилка не є корисною - програма вже була занадто заплутана.
Ви вже знаєте, що помилка з боку ~, як це працює $HOMEзамість цього.

Проблема: ~замінюється лише на початку слова.

Наприклад, це працює з тильдою:

echo -extract ~/Downloads

Якщо вам потрібен синтаксис опцій з =, використання $ HOME замість, ~є найчистішим рішенням;

echo -extract=$HOME/Downloads

Практика

Що ви повинні знати:

Існують спеціальні випадки, коли ~розгортання отримується, коли не на початку слова: як частина змінної задачі, безпосередньо після =. Звичайно, що тут заплутано.

Інший важливий особливий випадок - це для використання зі змінними на зразок PATH. У змінних призначеннях ~також розширюється після :, як і після першого =.

$ dir=~ sh -c 'echo D2: $dir'
D2: /home/user
$ sh -c 'echo D2: $dir' dir=~
D2: 
$ echo Dir: $dir
Dir:
$ dir=~; sh -c 'echo D2: $dir'
D2: 
$ echo Dir: $dir
Dir: /home/user
$ sh -c 'echo D2: $dir'; d3=~
D2: 
$ echo d3: $d3
d3: /home/user

Значення тильди

В оболонці ~тильда насправді не є стежкою. Він замінюється лише стежкою $HOME, в деяких випадках.

Це щось на зразок скорочення, або абревіатури, наданої оболонкою.
Його не можна використовувати як шлях взагалі, оболонка «розширює» його на шлях лише в дуже спеціальних місцях.
І навіть якщо він розширений, це може бути щось інше, ніж домашній каталог.

  • Він розгортається лише на початку слова або у призначенні змінної після a :або=
  • Він розширюється лише в тому випадку, якщо він не знаходиться всередині лапок
  • Він розширюється лише до того, $HOMEякщо в слові до слова "a" немає додаткових символів/

Проблема в командному рядку

Згідно з цим проблема вашої команди полягає в тому, що тильда в

-extract=~/Downloads/nvidia_installers

не розширюється, оскільки це не один із перелічених випадків. Це все.

Рішення може полягати в тому, щоб зробити тильду першим котируваним символом слова, не маючи іншого символу перед наступним, /- це саме те, що ви отримуєте, використовуючи параметр з пробілом перед аргументом параметра:

-extract ~/Downloads/nvidia_installers

Іншим рішенням буде $HOMEзамість цього використовувати . За сценарієм, це, як правило, кращий вибір.

-extract=$HOME/Downloads/nvidia_installers

Повідомлення про помилку

Але як повідомлення про помилку
"ERROR: extract: path must be absolute."?
вписатись у все це?

Ми знаємо, що тильда не розширилася. Це означає, що програма отримала текст аргументу, включаючи ~, але без /home/auserшляху. Цей шлях є ~/Downloads/nvidia_installers- але тепер немає оболонки, тому тильда не має особливого значення. Це просто звичайна назва каталогу. І як і будь-який інший шлях форми foo/bar/baz, це відносний шлях

Інші види використання

Якщо після символу є символи ~, як у ~alice- з усіма іншими правилами, наведеними вище, - а також є імена користувачів alice, які aliceзамість нього розширюються на домашній каталог home/alice.
Крім того, якщо ви є bob, ~то розширитесь /home/bobі ~bobна те саме.

Варіант ~+розширено до поточного каталогу,$PWD

Для посилання на попередній каталог, де ви були до останнього cd, ви можете використовувати ~-, до якого розширено $OLDPWD.

Якщо ви використовуєте pushdі popdзамість цього cd, ви вже будете знати, що до стека каталогів можна отримати доступ ~-2.

Деталі

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

Для точного визначення всередині оболонки, ось відповідний розділ Примітки, як заміна на лише один особливий випадок багатьох випадків: "Якщо це ім'я для входу є нульовим рядком, тильда замінюється значенням параметра оболонки HOME. " :man bash
~$HOME

Tilde Expansion
    If a word begins with an unquoted tilde character (`~'), all of the charac‐
    ters  preceding the first unquoted slash (or all characters, if there is no
    unquoted slash) are considered a tilde-prefix.  If none of  the  characters
    in  the tilde-prefix are quoted, the characters in the tilde-prefix follow‐
    ing the tilde are treated as a possible login name.  If this login name  is
    the  null string, the tilde is replaced with the value of the shell parame‐
    ter HOME.  If HOME is unset, the home directory of the user  executing  the
    shell is substituted instead.  Otherwise, the tilde-prefix is replaced with
    the home directory associated with the specified login name.

    If the tilde-prefix is a `~+', the value of the shell variable PWD replaces
    the  tilde-prefix.   If  the tilde-prefix is a `~-', the value of the shell
    variable OLDPWD, if it is set, is substituted.  If the characters following
    the tilde in the tilde-prefix consist of a number N, optionally prefixed by
    a `+' or a `-', the tilde-prefix is replaced with the corresponding element
    from  the  directory  stack,  as  it would be displayed by the dirs builtin
    invoked with the tilde-prefix as an argument.  If the characters  following
    the  tilde in the tilde-prefix consist of a number without a leading `+' or
    `-', `+' is assumed.

    If the login name is invalid, or the tilde expansion  fails,  the  word  is
    unchanged.

    Each variable assignment is checked for unquoted tilde-prefixes immediately
    following a : or the first =.  In these cases, tilde expansion is also per‐
    formed.   Consequently, one may use filenames with tildes in assignments to
    PATH, MAILPATH, and CDPATH, and the shell assigns the expanded value.

3

~- це не шлях сам по собі. Це персонаж, який отримує спеціальну обробку з оболонки, де ~або ~/означає "замінити на шлях до домашнього каталогу поточного користувача". ~usernameозначає "замінити на шлях до домашнього каталогу користувача".

Оскільки це не шлях, він розпізнається лише в певних місцях команди (як перший символ нового маркера, розділеного пробілом).

Коли він розширився, він замінив абсолютний шлях.

Використання $HOMEробіт, оскільки HOME - це просто змінна множина оболонки і дотримується звичайних правил оболонки для заміни змінної (це відбувається до того, як вхід розділений на пробіли та виконаний).


1

Ви праві. ~ / Завантаження - це те саме, що / home / username / Downloads.

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

Я просто звик замість цього вводити / home / username. :)

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