Считается ли тильда относительным путем?

35

Я пытаюсь извлечь другую часть установщика библиотеки nvidia cuda. Я использую следующую команду:

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 / likewise-open / XXX / username?

Проверено:

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

и это работает, но я не знаю, почему это не позволяет ~

Regan
источник
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 это (или , скорее , может быть настроен) расширяться ~после =тоже. Среди других удобных улучшений - Bash.
Ян Худек
@JanHudec Нет - все сложнее; Это не о расширении после =; речь идет о расширении в начале правой части присваивания переменной. Это делает наш случай немного более запутанным, если присмотреться - посмотрите мой ответ. И zshничем не отличается от bashэтого; Описание для zsh немного загадочно: info --subnodes zsh | less +/'14.7.4 Notes'(отсутствуют страницы руководства zsh)
Volker Siegel
1
@VolkerSiegel: zshочень настраиваемый. По моему зш echo -extract=~/testрезультаты -extract=/home/user/test. Это включено MAGIC_EQUAL_SUBSTопциями. Напомним, что у меня есть все справочные страницы zsh.
Ян Худек
@JanHudec Нет сомнений в том, zshчто можно настраивать - и другие улучшения; Я ожидал бы, что MAGIC_EQUAL_SUBST (описанный в 14.7.4) не установлен по умолчанию и используется редко; Теперь, очевидно, более уместно, если у вас это вообще включено. После того, как я приведу примерный раздел в хорошем состоянии, это будет хорошим дополнением ...
Volker Siegel
@JanHudec Что касается man-страниц zsh, они какое-то время отсутствовали в пакетах Ubuntu, спасибо за подсказку, не знал, что это было исправлено; Глядя на ошибку, она исправлена ​​для утопии, но не заслуживает доверия - это объясняет! ( панель запуска: все zsh-страницы и встроенные файлы справки отсутствуют и AU: zsh человек отсутствует ... )
Volker Siegel,
19

Просто исправляю

Эта команда показывает сообщение об ошибке «ОШИБКА: извлечение: путь должен быть абсолютным»:

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

Ошибка не помогает - программа уже слишком запуталась.
Вы уже знаете, что ошибка от ~, поскольку она работает $HOMEвместо этого.

Проблема: ~заменяется только в начале слова.

Например, это работает с тильдой:

echo -extract ~/Downloads

Если вам нужен синтаксис с опцией =, использование $ HOME вместо ~наиболее чистого решения;

echo -extract=$HOME/Downloads

Практика

То, что вы должны знать:

Существуют особые случаи, когда ~get расширяется, когда не в начале слова: как часть присваивания переменной, сразу после= . Что, конечно, сбивает с толку.

Другой важный особый случай - использование с такими переменными, как 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 несколько раз.

Это что-то вроде сокращения или сокращения, предоставляемого оболочкой.
Его нельзя использовать как путь в целом, оболочка «расширяет» его до пути только в очень особых местах.
И даже если он расширен, он может быть чем-то другим, кроме домашнего каталога.

  • Он раскрывается только в начале слова или в присваивании переменной после :или=
  • Расширяется только если не в кавычках
  • Он раскрывается только в том $HOMEслучае, если в слове нет следующих символов перед/

Проблема в командной строке

В соответствии с этим, проблема в вашей команде заключается в том, что тильда в

-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.
Volker Siegel
источник
3

~это не путь сам по себе. Это персонаж, который получает специальную обработку из оболочки, где ~или ~/означает «заменить на путь к домашнему каталогу текущего пользователя».~usernameозначает «заменить на путь к домашней директории пользователя».

Поскольку это не путь, он распознается только в определенных местах команды (как первый символ нового токена с разделением пробелами).

При расширении он заменяется абсолютным путем.

Использование $HOMEработает, потому что HOME - это просто переменная, установленная оболочкой, и она следует обычным правилам оболочки для замены переменных (это происходит до того, как ввод разделен на пробелы и выполнен).

Daenyth
источник
1

Ты прав. ~ / Downloads такой же, как / home / username / Downloads.

Некоторые инсталляторы и экстракторы очень разборчивы в том, куда нужно поместить вещи. Я думаю, что это может быть потому, что он регистрирует пути к файлам, и журналы не принимают ~ по принятому пути.

Я просто привык вместо этого вводить / home / username. :)

Дэн Йохансен
источник