Por que não consigo fazer o cd para um til citado ('~')?


32

Escrevendo meu primeiro script, para ter certeza de que esta é uma pergunta básica, mas alguém pode me explicar por que posso:

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

Mas não

cd '~'
cd '~/bin'

Eu preciso de cdum caminho de diretório com um espaço em um dos nomes de diretório, por isso preciso das aspas (é Windows Program Filesno wine). Posso contornar isso com dois cdcomandos, mas por que não consigo colocar ~aspas?

Se eu digitar cd '~'(ou cd "~"), recebo:

bash: cd: ~: No such file or directory

29
Pergunte a si mesmo: se não funcionasse dessa maneira, como você entraria cdem um diretório chamado ~?
Jörg W Mittag

2
Como nota de rodapé, se você estiver escrevendo um script, use caminhos absolutos e evite tudo cd. Use variáveis para armazenar nomes de caminhos que você não deseja digitar várias vezes, por exemplopf=~/.wine/drive_c/Program\ Files/; cp /path/to/file "$pf"
sobremesa

8
@ jamesqf: Por que um sistema sensato presumiria saber melhor do que eu o que eu quero nomear meus arquivos e diretórios? Além disso, eu nunca entendi por que o Unix utilizou a sinalização mágica em banda dos separadores e terminadores de componentes de caminho. O que há de errado com um arquivo / diretório chamado /ou NUL?
Jörg W Mittag

3
@ JörgWMittag presumivelmentecd ./~
k_g

2
@jamesqf Apenas para observar que, historicamente, os sistemas de arquivos Unix permitiam qualquer caractere em um nome de arquivo, exceto '/' (separador de caminho) e '\ 0' (NUL - caracter de terminação de string) - como observa Jorg. Sem outras restrições. Existem muitas implementações de sistemas de arquivos Unix, portanto, a introdução de restrições em qualquer uma delas quebraria a compatibilidade e aumentaria a complexidade - e era vista como "estranha"! E a expansão '~' foi introduzida apenas comparativamente recentemente no csh e mais amplamente no bash, arquivos / diretórios com '~' chars in não são desconhecidos (por exemplo, myfile ~ como um backup para o myfile).
SusanW

Respostas:


78

Como @karel observou em sua resposta, ~é um caractere especial e expandido por Bash no diretório inicial do usuário atual. Consulte o manual de Bash em "Expansão de til" ou procure o título "Expansão de til" na página de manual ( man bash).

Qualquer tipo de cotação em torno do ~impede essa expansão de til.


Para responder sua pergunta sobre como você ainda pode usá-lo cdem um diretório com espaços em seu nome, existem algumas alternativas:

  • Omita aspas e escape dos espaços com barras invertidas:

    cd ~/foo/spaces\ are\ cool/bar
  • Cite o restante do caminho, mas omita-o no til e na primeira barra:

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

    Como você vê, você pode concatenar seqüências de caracteres entre aspas e não entre aspas no Bash, simplesmente escrevendo-as próximas umas das outras, sem espaços entre elas.

  • Use a variável de ambiente em $HOMEvez do til, que ainda é expandido entre "aspas duplas" (mas não 'aspas simples'):

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

3
@rexkogitans ~'/...'não vai funcionar e não é o que esta resposta tem. ~/'...'ou ~/"..."vai funcionar.
hvd 5/05

TLD; dr: porque isso é sintaxe shell
Sergiy Kolodyazhnyy

@hvd obrigado. Corrigido erro de digitação. Essa é a resposta mais completa e também explica como resolver o que o OP deseja fazer. ~/'path'é o caminho a percorrer.
Rexkogitans

1
@ hvd apenas um pouco de curiosidade, por que não ~'/...'funcionaria? A barra não é um caractere especial, portanto parece que deve funcionar dentro ou fora das aspas.
Kodos Johnson

6
@KodosJohnson Dê uma olhada na seção da página de manual do Bash sobre "Tilde Expansion". O parágrafo relevante disso também é citado na resposta da sobremesa abaixo. TL; DR: a expansão do til ocorre se o primeiro caractere de uma palavra é um til sem aspas, então tudo entre esse til e a próxima barra sem aspas é considerado o "prefixo til". Se esse prefixo não for válido, como +, -, um número ou um nome de usuário (as aspas também não são permitidas), a expansão falhará e você obterá um caractere ~ literal.
Byte Commander

17

~ é um caractere especial que é interpretado pelo shell como o diretório inicial do usuário conectado. '~' é interpretado pelo shell como um caractere literal, e não como o diretório inicial do usuário logado, porque incluir uma cadeia dentro de dois caracteres de aspas simples faz com que a cadeia seja interpretada como uma cadeia de texto literal.


~não é um apelido no sentido em que o bashinterpreta: os apelidos permitem que uma sequência seja substituída por uma palavra quando é usada como a primeira palavra de um comando simples. . Como explico na minha resposta abaixo, é uma expansão.
dessert

15

Esse é um bashrecurso chamado Tilde Expansion . Citação man bash:

Se uma palavra começar com um caractere de til sem aspas (`~ '), todos os caracteres que precedem a primeira barra sem aspas (ou todos os caracteres, se não houver uma barra sem aspas) serão considerados um prefixo de til. Se nenhum dos caracteres no prefixo de til for citado, os caracteres no prefixo de til após o til serão tratados como um possível nome de login. Se esse nome de login for a cadeia nula, o til será substituído pelo valor do parâmetro do shell HOME. Se HOME estiver desabilitado, o diretório inicial do usuário que está executando o shell será substituído.

Para que a expansão funcione, o caractere til ~precisa ser não citado, caso contrário, o caractere é interpretado literalmente e cdfalhará se não houver um diretório nomeado ~presente no diretório atual. Veja esta resposta extensa para obter uma explicação sobre como citar bash. Se você precisar citar parte do caminho, poderá:

  1. cite pelo menos os caracteres que precisam ser citados com aspas simples, por exemplo

    ~/dir' 'with' 'spaces/

    ou

    ~/'dir with spaces/'
  2. cite pelo menos os caracteres que precisam de aspas duplas, por exemplo

    ~/dir" "with" "spaces/

    ou

    ~/"dir with spaces/"
  3. cite apenas os caracteres que precisam ser citados com barras invertidas, por exemplo

    ~/dir\ with\ spaces/

A Expansão Tilde tem alguns recursos mais interessantes, por exemplo:

  • ~+expande para o valor de PWD, ou seja, o diretório de trabalho atual
  • ~-expande para o valor de OLDPWD, ou seja, o diretório de trabalho anterior
  • ~john expande para o diretório inicial associado ao nome de login "john"

Aliás, não há problema em "citar demais" também com barras invertidas; por exemplo $ touch a; cd \a,. (Eu pensei que isso poderia ter problemas com cd \n, mas a experimentação, pelo menos na minha versão de bashsugere ele funciona bem.)
LSpice

1

Explorar usando o echocomando

A maneira mais fácil de explorar como as coisas funcionam no bash é com o echocomando No caso de ~usar isto:

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

Como você pode ver, quando você aspas simples ou aspas duplas ~é interpretado literalmente como uma string e não expandido como uma variável. Quando você usa backticks (`), ele é executado como um comando e gera uma mensagem de erro.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.