Por que o mkdir falha (sem esse arquivo ou diretório) em um script com BIN_DIR = “~ / bin /”?

Respostas:

11

A mensagem de erro é produzida porque o til ~é citado, conforme descrito na resposta de Zanna . Se você deseja usar o ~, a parte relevante do script deve ser:

BIN_DIR=~/bin/

Se, por qualquer motivo, você desejar citar a sequência, poderá usar a variável de ambiente $HOME:

BIN_DIR="$HOME/bin/"

Na minha opinião, a segunda abordagem é a melhor prática.

pa4080
fonte
6
Não há nada errado em usar ~scripts. funciona exatamente da mesma maneira que na linha de comando. O problema é que a cotação bloqueia a expansão do til, conforme explicado na resposta de Zanna .
terdon
@terdon, eu concordo. Mas eu não disse que há algo errado, mas é uma idéia melhor, porque você deve prestar menos atenção.
pa4080
5
Mas não há absolutamente nenhuma diferença entre a linha de comando e um script aqui. O fato de isso estar em um script é completamente irrelevante, você teria exatamente o mesmo erro na linha de comando. A questão é a citação, não que esteja em um script.
Terdon · 17/11
Embora isso seja totalmente verdade, também é correto que usar $HOMEscripts seja uma boa ideia.
Dessert
3
@ pa4080 Você pode adicionar uma explicação de por que você acha melhor expandir $HOMEdo que usar a expansão til? A única explicação que você deu é dizer: "é uma idéia melhor, porque você deve prestar menos atenção". Eu não tenho idéia o que isso significa. Você pode explicar isso em uma edição? Sem ele, não há nada que apóie sua resposta, então com certeza ela pertence a ela. A expansão de til foi solicitada pelo POSIX por um bom tempo e a linha hashbang do script é, #!/bin/bashportanto, suponho que a portabilidade não seja o motivo.
Eliah Kagan 17/11
23

Não funciona porque ~é citado. Aspas duplas " suprimem a expansão do til . Não há diretório com o nome literal ~/bin. Conforme explicado em man bash(ênfase minha):

Expansão Tilde

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. Caso contrário, o prefixo til será substituído pelo diretório inicial associado ao nome de login especificado.

Você pode remover as aspas , pois ~é o único caractere no caminho ~/binque fará com que o shell execute uma expansão, e queremos a expansão nesse caso. O shell não fará mais expansões no resultado da expansão til, pelo menos no Bash 4 , que todas as versões atuais ou remotamente recentes do Ubuntu têm . Portanto, mesmo que seu diretório pessoal contenha caracteres incomuns, como espaços, tudo bem.

Ou você pode usar em $HOMEvez de ~, porque a expansão do parâmetro não é suprimida por aspas duplas, apenas por aspas simples . As aspas não garantir que o valor expandido não é por si só dependente de outras expansões, então repartição de palavras ou expansão filename não ocorrerá. Também $HOMEfunciona com diretórios pessoais com nomes estranhos, desde que você mantenha aspas duplas.

Zanna
fonte
De acordo com esta afirmação "a expansão do parâmetro não é suprimida por aspas duplas, apenas por aspas simples" : a saída de cd '~'é -bash: cd: ~: No such file or directory.
precisa
2
@ pa4080 A expansão de ~não faz parte da expansão de parâmetros.
Barmar