Ao tentar originar um arquivo, você não gostaria de um erro dizendo que o arquivo não existe para saber o que corrigir?
Por exemplo, a nvm recomenda adicionar isso ao seu perfil / rc:
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
Com o exposto acima, se nvm.sh
não existir, você receberá um "erro silencioso". Mas se você tentar . "$NVM_DIR/nvm.sh"
, a saída será FILE_PATH: No such file or directory
.
shell-script
JBallin
fonte
fonte
HOME
.Respostas:
Nos shells POSIX,
.
é um built-in especial, portanto, sua falha faz com que o shell seja encerrado (em alguns shellsbash
, isso é feito apenas no modo POSIX).O que qualifica como um erro depende do shell. Nem todos saem com um erro de sintaxe ao analisar o arquivo, mas a maioria sai quando o arquivo de origem não pode ser encontrado ou aberto. Não conheço nenhum que sairia se o último comando no arquivo de origem retornasse com um status de saída diferente de zero (a menos que a
errexit
opção esteja ativada).Aqui fazendo:
É um caso em que você deseja originar o arquivo, se estiver lá, e não, se não estiver (ou estiver vazio aqui com
-s
).Ou seja, não deve ser considerado um erro (erro fatal nos shells POSIX) se o arquivo não estiver lá, esse arquivo será considerado um arquivo opcional.
Ainda seria um erro (fatal) se o arquivo não fosse legível ou fosse um diretório ou (em alguns shells) se houvesse um erro de sintaxe ao analisá-lo, o que seriam condições reais de erro que deveriam ser relatadas.
Alguns argumentam que há uma condição de corrida. Mas a única coisa que isso significa seria que o shell sairia com um erro se o arquivo fosse removido entre
[
e.
, mas eu diria que é válido considerar um erro que esse arquivo de caminho fixo desapareça repentinamente enquanto o script é corrida.Por outro lado,
em que
command
¹ remove o atributo especial do.
comando (para que ele não saia do shell por erro) não funcionaria como:.
os erros, mas também os erros dos comandos executados no arquivo de origemOutras sintaxes comuns (veja, por exemplo,
grep -r /etc/default /etc/init*
nos sistemas Debian, os scripts init que ainda não foram convertidossystemd
(ondeEnvironmentFile=-/etc/default/service
é usado para especificar um arquivo de ambiente opcional)) incluem:[ -e "$file" ] && . "$file"
Verifique o arquivo que está lá, ainda o fonte se estiver vazio. Ainda erro fatal se não puder ser aberto (mesmo que esteja lá ou existisse). Você pode ver mais variantes como
[ -f "$file" ]
(existe e é um arquivo arquivo ),[ -r "$file" ]
(é legível) ou combinações delas.[ ! -e "$file" ] || . "$file"
Uma versão um pouco melhor. Torna mais claro que o arquivo não existente é um caso OK. Isso também significa
$?
que refletirá o status de saída do último comando executado$file
(no caso anterior, se você receber1
, não sabe se é porque$file
não existia ou se esse comando falhou).command . "$file"
Espere que o arquivo esteja lá, mas não saia se não puder ser interpretado.
[ ! -e "$file" ] || command . "$file"
Combinação do que foi dito acima: tudo bem se o arquivo não estiver lá e, para shells POSIX, falhas ao abrir (ou analisar) o arquivo são relatadas, mas não são fatais (o que pode ser mais desejável para
~/.profile
).¹ Nota: No
zsh
entanto, você não pode usarcommand
assim, a menos que sejash
emulado; note que no shell Korn,source
na verdade é um alias paracommand .
, uma variante não especial de.
fonte
.bash_profile
. Acho melhor prevenir do que remediar, mas o bash está sempre no modo POSIX quando.bash_profile
é fornecido?bash
quando não estiver no modo POSIX. Você desejaria[ -e /file ] && . /file
se não considerasse um erro quando o arquivo não existe. A fonte try então lida com o erro, se não for possível fazer aqui..
já reportará um erro (no stderr). E se a intenção é não considerar um erro quando o arquivo não existe, isso não está correto (e não é possível, no status de saída, dizer se.
falhou porque o arquivo não existia ou não era legível ou estava não pode ser analisado ou o último comando falhou), que são os pontos que estou fazendo aqui nesta resposta.Mantenedor de
nvm
resposta de:Minha interpretação (combinada com a excelente explicação de Stéphane e o comentário de Kusalananda):
É mais simples e seguro.
Ele defende contra shells POSIX que saem na inicialização devido a um arquivo ausente (por vários motivos). Aqueles que usam shells não POSIX (por exemplo, bash) podem remover o condicional, se preferirem.
fonte
/etc
, isso permitirá que alguns usuários tenham o arquivo e outros não. IMHO, anvm
resposta do mantenedor está apenas tocando em um aspecto.Como JBallin e Stéphane Chazelas apontaram, nos shells do POSIX, o fornecimento de um arquivo que não existe causaria falha no login.
Porém, adicionar um teste para ver se o arquivo existe e, em seguida, tentar originar ele pode causar algo chamado condição de corrida. Se algo mudar
nvm.sh
entre o[ -s nvm.sh ]
e o. nvm.sh
, causará exatamente o erro que eles estão tentando impedir, embora muito mais raramente.Em geral, a maneira de impedir as condições da corrida é apenas tentar o que você deseja fazer e depois lidar com o erro se ele falhar, por exemplo,
Acontece que isso não funciona em shells POSIX, porque, como acima,
.
falhar fará com que o shell saia imediatamente, antes que qualquer manipulação de erro possa ser executada.Minha resposta argumenta que as conchas POSIX não são relevantes para esta questão, porque
.bash_profile
nunca devem ser executados no modo POSIX. Assim, podemos apenas fazer o código acima de qualquer maneira.Para ser mais seguro, podemos garantir que o modo POSIX não esteja em vigor ou garantir que o modo POSIX esteja desativado usando a técnica descrita em /unix//a/383581/3169 .
A resposta de Stéphane tem algumas sugestões úteis sobre como lidar com todos os shells POSIX, que eu acho que era a intenção do autor da nvm, mas era sutilmente diferente do que a pergunta aqui estava perguntando, e é por isso que temos várias abordagens possíveis, dependendo do seu objetivo. .
fonte