波浪号(〜)是否被视为相对路径?


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

它有效,但是我不知道为什么它不允许 ~


2
相关: “一个“波浪号前缀”由单词开头的无引号<tilde>字符组成,后跟所有第一个未引号的字符”
Braiam 2014年

Answers:


47

如果Bash是单词的开头,则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

与plain一样~,这些可以在末尾添加其他路径,同样,这些必须是单词的前缀,否则Bash会忽略它们。

您可以在以下内容中了解更多信息 man bash | less -p ' Tilde'


2
值得一提的是,zsh (或者更确切地说,可以配置成)扩大~=了。除其他方便的改进外,它还超过了bash。
2014年

@JanHudec不-它更复杂;它不是关于事后扩大=;它是关于在变量的右侧右边开始扩展。当仔细观察时,这会使我们的情况更加混乱-请参阅我的答案。与此zsh没有什么不同bash;“ zsh”的描述有些神秘:(info --subnodes zsh | less +/'14.7.4 Notes'缺少zsh手册页)
Volker Siegel 2014年

1
@VolkerSiegel:zsh非常可配置。在我的zsh echo -extract=~/test结果中-extract=/home/user/test。它由MAGIC_EQUAL_SUBST选项启用。附带一提,我确实所有zsh手册页都很好。
Jan Hudec 2014年

@JanHudec毫无疑问zsh是可配置的-其他改进;我本来希望MAGIC_EQUAL_SUBST(在14.7.4中介绍过)是默认未设置的,并且很少使用。现在,如果您一般启用它,则显然更相关。在我的示例部分状况良好之后,这将是一个不错的补充……
Volker Siegel 2014年

@JanHudec关于zsh手册页,Ubuntu软件包中有一段时间缺少它们了,感谢您的提示,不知道该问题已得到解决。查看该错误,该错误已针对utopic进行了修复,但并不可靠-可以解释!(启动板:所有zsh联机帮助页和内联帮助文件均丢失,AU:zsh man缺失...
Volker Siegel 2014年

19

修好它

此命令显示错误消息“错误:提取:路径必须是绝对的”:

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

该错误无济于事-该程序已经太混乱了。
您已经知道错误来自~,因为可以使用$HOME

问题:~仅在单词开头替换。

例如,这适用于波浪号:

echo -extract ~/Downloads

如果您需要使用选项语法=,则使用$ HOME代替~是最干净的解决方案;

echo -extract=$HOME/Downloads

实践

您应该知道的是:

在某些特殊情况下,~get不在单词开头时进行扩展:作为变量赋值的一部分,紧接在=。之后。当然,这令人困惑。

另一个重要的特殊情况是与PATH等变量一起使用。在变量赋值中,在first之后~也进行扩展。:=

$ 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

波浪号的含义

在shell中,~代字号不是真正的路径。$HOME有时,它仅被路径替换。

它是外壳程序提供的速记或缩写之类的东西。
通常,它不能像路径一样使用,shell仅在非常特殊的地方将其“扩展”为路径。
即使它被扩展,它也可以位于主目录以外的其他位置。

  • 它仅在扩展一个单词的开头,或在一个变量赋值后:=
  • 仅当它不在引号内时才展开
  • $HOME当单词a之前没有其他字符时才扩展/

命令行中的问题

据此,您命令中的问题是波浪号

-extract=~/Downloads/nvidia_installers

不会扩展,因为它不是列出的情况之一。就这样。

解决方案可能是使波浪号成为单词的第一个未加引号的字符,而在下一个字符前没有其他字符/-这就是在使用option参数时在option参数前加空格时得到的结果:

-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,则将其扩展到home目录,alice而不是说home/alice
另外,如果您是bob~则将扩展为/home/bob,然后~bob将其扩展为相同的值。

该变体~+被扩展到当前目录,$PWD

要引用上一个目录(位于上一个目录之前)cd,可以使用~-,将其扩展为$OLDPWD

如果使用pushdpopd而不是cd,您将已经知道可以像那样访问目录堆栈~-2

细节

外壳会处理所有~扩展到路径的情况。对于其他程序,~只是普通的文件名字符。

对于确切的定义在外壳内部,这里的相关章节 说明如何更换的只是一个的情况很多特殊情况:“如果这个登录名是空字符串,波浪线将被替换为shell参数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之所以使用Works是因为HOME只是由shell设置的变量,并且遵循普通的shell规则进行变量替换(它发生在将输入分割成空格并执行之前)。


1

你是对的。〜/ Downloads与/ home / username / Downloads相同。

一些安装程序和提取程序对于将内容放置在什么地方非常挑剔。我认为这可能是因为它记录了文件路径,并且日志不会在可接受的路径中接受〜。

我只是习惯于输入/ home / username而已。:)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.