Qual é a diferença entre com um ~ e sem um ~ em uma variável de string no Bash? [duplicado]

3

Estou usando um software de gerenciamento de arquivo pontuado chamado dotdrop . Usando um arquivo de configuração chamado .env , conteúdo como: git_folder="~/code/Git" .

Use também um script para configurar essa ferramenta dotfile antes do primeiro uso, como segue,

#!/bin/bash

env1="~/Dropbox/.env"
env2="/mnt/d/Dropbox/.env"

if [ -f $env1 ]; then
    echo "Found dotdrop env file, installing dotfiles..."
    source $env1
    eval $(grep -v "^#" $env1) dotdrop --cfg=${git_folder}/dotfiles/config.yaml install
elif [ -f $env2 ]; then
    echo "Found dotdrop env file, installing dotfiles..."
    source $env2
    eval $(grep -v "^#" $env2) dotdrop --cfg=${git_folder}/dotfiles/config.yaml install
else echo "Pls sync environment files first!"
fi

Se eu armazenar meu arquivo de configuração em ~/Dropbox/.env , quando eu executar o script, acabei de receber "Pls sync environment files first!" (executado se a condição for esperada). Se o arquivo de configuração for armazenado em /mnt/d/Dropbox/.env , o script passará pela condição elif, o que é esperado.

Encontre o motivo até que eu execute o script no modo de dubug e obtenha a diferença:

➜  scripts git:(master) ✗ bash -x dotdrop_setup.sh 
+ env1='~/Dropbox/.env'
+ env2=/mnt/d/Dropbox/.env
+ '[' -f '~/Dropbox/.env' ']'
+ '[' -f /mnt/d/Dropbox/.env ']'
+ echo 'Pls sync environment files first!'
Pls sync environment files first!

Então, acho que a diferença entre ~ e /home/user é o motivo.

Depois que eu mudo ~ para /home/roach (o roach é o nome de usuário), funciona.

➜  scripts git:(master) ✗ bash -x dotdrop_setup.sh
+ env1=/home/roach/Dropbox/.env
+ env2=/mnt/d/Dropbox/.env
+ '[' -f /home/roach/Dropbox/.env ']'
+ echo 'Found dotdrop env file, installing dotfiles...'
Found dotdrop env file, installing dotfiles...
+ source /home/roach/Dropbox/.env
++ git_folder='~/code/Git'
++ grep -v '^#' /home/roach/Dropbox/.env
+ eval git_folder='~/code/Git'
++ dotdrop '--cfg=~/code/Git/dotfiles/config.yaml' install
     _       _      _
  __| | ___ | |_ __| |_ __ ___  _ __
 / _' |/ _ \| __/ _' | '__/ _ \| '_ |
 \__,_|\___/ \__\__,_|_|  \___/| .__/  v0.22.0
                               |_|


0 dotfile(s) installed.

A depuração mostra que '' surround + env1='~/Dropbox/.env' foi removido, o que acredito ser o motivo.

Mas, POR QUE ?

Pergunta adicional,

alias dotdrop="eval $(grep -v "^#" $env1) /usr/bin/dotdrop --cfg=${git_folder}/dotfiles/config.yaml install" é uma adição de configuração a bashrc , zshrc , etc. Não funciona se eu adicioná-lo diretamente ao meu script!

Finalmente, descobri que preciso adicionar source $env

Então, POR QUE funciona em um arquivo bashrc?

    
por roachsinai 22.10.2018 / 08:09

1 resposta

11

~ é um atalho para o seu diretório pessoal, mas apenas quando aparece no início de uma string entre aspas externas . O início do lado direito de um operador de atribuição é o começo de uma string, então env1=~/Dropbox/.env funcionaria (ou env1=~"/Dropbox/.env" ou qualquer número de variações). Define env1 para /home/roach/Dropbox/.env . Mas env1="~/Dropbox/.env" define env1 para a exata string ~/Dropbox/.env , que como um nome de arquivo procura dentro de um diretório com o nome de um caractere ~ no diretório atual.

til é uma abreviação, não um curinga. $env1 fora de aspas expande curingas no valor de env1 , mas não expande o til porque o til não é um caractere curinga.

Você também pode usar env1="$HOME/Dropbox/.env" . Isso é equivalente a env1=~/Dropbox/.env . O caractere $ (dólar) tem um significado especial entre aspas duplas (é o mesmo significado que as aspas externas): ele inicia uma substituição de variável (ou um comando ou uma substituição aritmética). O caractere ~ (til), por outro lado, é apenas um caractere comum quando está entre aspas, até mesmo aspas duplas.

Quanto ao alias, o motivo pelo qual ele não funciona em um script bash é que o bash não expande aliases em scripts por padrão. Ele não funcionará em nenhum script, a menos que você inclua ou forneça a definição do alias nesse script, já que os aliases são uma propriedade de cada instância do shell. Eles não fazem parte do ambiente de um processo.

O motivo pelo qual o alias funciona em seu segundo script é que o próprio dotdrop expande o til quando lê seu valor de configuração.

    
por 22.10.2018 / 08:46