O til, '~' é considerado um caminho relativo?

33

Estou tentando extrair a parte diferente do instalador da biblioteca Nvidia cuda. Estou usando o seguinte comando:

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

E recebo a seguinte mensagem:

ERROR: extract: path must be absolute.

E quando eu digito o comando com o endereço literal da minha casa, ele funciona perfeitamente.

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

Estou confuso que não deveria ser o mesmo de / home / likewise-open / XXX / username?

Testado:

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

e funciona, mas não sei porque não permite ~

    
por Regan 27.08.2014 / 15:19

4 respostas

45

Bash apenas expande um ~ se for o começo de uma palavra. Você pode ver isso entre os seguintes comandos:

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

[email protected]:~$ echo -extract ~/test
-extract /home/oli/test

O Bash procura por ~ caracteres autônomos e ~/ para essa substituição. Nenhuma outra combinação ou versão citada funcionará.

$HOME funciona porque as substituições de variáveis ​​são mais robustas (o $ é um caractere especial, enquanto ~ é muito menos):

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

Enquanto estamos falando de ~ , ele realmente tem outro par de outros usos de substituição:

  • ~+ do diretório de trabalho atual (lido em $PWD )
  • ~- do diretório de trabalho anterior (lido em $OLDPWD )

Como no ~ simples, eles podem ter caminhos adicionais no final e, novamente, eles devem ser o prefixo de uma palavra ou o Bash os ignorará.

Você pode ler mais sobre isso em man bash | less -p ' Tilde'

    
por Oli 27.08.2014 / 15:35
19

Apenas consertando

Este comando mostra uma mensagem de erro "ERRO: extrair: o caminho deve ser absoluto":

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

O erro não é útil - o programa já estava muito confuso.
Você já sabe que o erro é do ~ , pois funciona com $HOME .

O problema: ~ só é substituído no início de uma palavra.

Por exemplo, isso funciona com o til:

echo -extract ~/Downloads

Se você precisar da sintaxe da opção com = , usar $ HOME em vez de ~ é a solução mais limpa;

echo -extract=$HOME/Downloads

A prática

O que você deve saber:

Existem casos especiais em que ~ get é expandido quando não está no início de uma palavra: como parte de uma atribuição de variável, diretamente após o = . O que é confuso aqui, claro.

O outro caso especial importante para uso com variáveis ​​como o PATH. Em atribuições de variáveis, ~ também é expandido após : , como após o primeiro = .

$ 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

O significado do til

Em um shell, ~ , o til, não é realmente um caminho. Só é substituído por um caminho, $HOME , algumas vezes.

É algo como uma abreviação, ou abreviação, fornecida pelo shell.
Não pode ser usado como um caminho em geral, o shell "expande-o" para um caminho apenas em lugares muito especiais.
E mesmo que seja expandido, pode ser para algo diferente do diretório inicial.

  • Só é expandido no início de uma palavra ou em uma atribuição de variável após um : ou =
  • Só é expandido se não estiver entre aspas
  • Só é expandido para $HOME se houver sem mais caracteres na palavra antes de um /

O problema na linha de comando

De acordo com isso, o problema em seu comando é que o til em

-extract=~/Downloads/nvidia_installers

não é expandido, porque não é um dos casos listados. Isso é tudo.

A solução poderia ser tornar o til o primeiro caractere sem aspas de uma palavra, sem nenhum outro caractere antes do próximo / - é exatamente o que você obtém quando usa uma opção com um espaço antes do argumento da opção:

-extract ~/Downloads/nvidia_installers

Outra solução seria usar $HOME . Em um script, geralmente é a melhor escolha.

-extract=$HOME/Downloads/nvidia_installers

A mensagem de erro

Mas como a mensagem de erro
"ERROR: extract: path must be absolute." ?
se encaixa em tudo isso?

Sabemos que o til não foi expandido. Isso significa que o programa obteve o texto do argumento incluindo o ~ , mas sem o /home/auser como o caminho. Esse caminho é ~/Downloads/nvidia_installers - mas agora não há shell, então o til não tem nenhum significado especial. É apenas um nome de diretório normal. E como todos os outros caminhos da forma foo/bar/baz , é um caminho relativo

Outros usos

Se houver caracteres após o ~ , como em ~alice - com todas as outras regras acima aplicáveis ​​- e houver um nome de usuário alice , que será expandido para o diretório inicial de alice , diga home/alice .
Além disso, se você for bob , ~ expandiria para /home/bob e ~bob expandiria para o mesmo.

A variante ~+ é expandida para o diretório atual, $PWD

Para se referir ao diretório anterior, onde você estava antes do último cd , você pode usar ~- , que é expandido para $OLDPWD .

Se você usar pushd e popd , em vez de cd , já saberá que a pilha de diretórios pode ser acessada como ~-2 .

Detalhes

Todos os casos em que ~ é expandido para um caminho são distribuídos pelo shell . Para outros programas, ~ é apenas um caractere normal de nome de arquivo.

Para a definição exata dentro do shell, aqui está a seção relevante de man bash
Observe como a substituição de ~ por $HOME é apenas um caso especial de muitos casos: "Se esse nome de login for a cadeia nula, o til será substituído pelo valor do parâmetro da shell 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.
    
por Volker Siegel 27.08.2014 / 17:08
3

~ não é um caminho por si só. É um caractere que recebe tratamento especial do shell em que ~ ou ~/ significa "substituir pelo caminho do diretório inicial do usuário atual". ~username significa "substituir pelo caminho do diretório de usuário do nome de usuário".

Como não é um caminho, ele é reconhecido apenas em determinados locais no comando (como o primeiro caractere de um novo token de divisão de espaço).

Quando expandido, ele é substituído por um caminho absoluto.

Usar $HOME funciona porque HOME é apenas uma variável definida pelo shell e segue regras normais de shell para substituição de variáveis ​​(isso acontece antes de a entrada ser dividida em espaços e executada).

    
por Daenyth 27.08.2014 / 15:54
1

Você está correto. o ~ / Downloads é o mesmo que / home / username / Downloads.

Alguns instaladores e extratores são muito exigentes sobre onde precisa colocar as coisas. Eu acho que pode ser porque ele registra os caminhos de arquivo, e os logs não aceitarão ~ em um caminho aceito.

Acabei de me acostumar a digitar / home / username. :)

    
por Dan Johansen 27.08.2014 / 15:24