Dans un shell donné, normalement je définirais une ou plusieurs variables, puis exécuterais une commande. Récemment, j'ai découvert le concept de l'ajout d'une définition de variable à une commande:
FOO=bar somecommand someargs
Cela fonctionne ... en quelque sorte. Cela ne fonctionne pas lorsque vous modifiez une variable LC_ * (qui semble affecter la commande, mais pas ses arguments, par exemple, les plages de caractères '[az]') ou lorsque vous redirigez la sortie vers une autre commande:
FOO=bar somecommand someargs | somecommand2 # somecommand2 is unaware of FOO
Je peux également ajouter une commande2 à "FOO = bar", ce qui fonctionne, mais qui ajoute une duplication indésirable, et cela n'aide pas avec les arguments qui sont interprétés en fonction de la variable (par exemple, '[az]').
Alors, quelle est la bonne façon de le faire sur une seule ligne?
Je pense à quelque chose de l'ordre de:
FOO=bar (somecommand someargs | somecommand2) # Doesn't actually work
J'ai eu plein de bonnes réponses! Le but est de garder cette ligne unique, de préférence sans utiliser "d'export". La méthode utilisant un appel à Bash était globalement la meilleure, bien que la version entre parenthèses avec "export" soit un peu plus compacte. La méthode d'utilisation de la redirection plutôt que d'un tuyau est également intéressante.
la source
(T=$(date) echo $T)
fonctionneraRéponses:
la source
somecommand
as sudo, vous devez passer le-E
drapeau sudo pour passer à travers les variables. Parce que les variables peuvent introduire des vulnérabilités. stackoverflow.com/a/8633575/1695680FOO_X=foox bash -c 'echo $FOO_X'
fonctionne comme prévu mais avec des noms var spécifiques, il échoue:DYLD_X=foox bash -c 'echo $DYLD_X'
échos en blanc. les deux fonctionnent en utilisanteval
au lieu debash -c
Que diriez-vous d'exporter la variable, mais uniquement à l'intérieur du sous-shell?:
Keith a un point, pour exécuter inconditionnellement les commandes, procédez comme suit:
la source
;
plutôt que&&
; il n'y a aucun moyenexport FOO=bar
d'échouer.&&
exécute la commande gauche, puis exécute la commande droite uniquement si la commande gauche a réussi.;
exécute les deux commandes sans condition. L'cmd.exe
équivalent Windows batch ( ) de;
est&
.(FOO=XXX ; echo FOO=$FOO) ; echo FOO=$FOO
rendementsFOO=XXX\nFOO=\n
.source
(aka.
) dans ce cas? De plus, les backticks ne devraient plus être utilisés de nos jours et c'est l'une des raisons pour lesquelles, l'utilisation$(command)
est waaaaay plus sûre.bash
mais pourrait être autre chose, par exempledash
) et je n'ai aucun problème si je dois utiliser des guillemets dans la commande args (someargs
).Vous pouvez également utiliser
eval
:Étant donné que cette réponse
eval
ne semble pas plaire à tout le monde, permettez-moi de clarifier une chose: lorsqu'elle est utilisée telle qu'elle est écrite, avec les guillemets simples , elle est parfaitement sûre. C'est bien car il ne lancera pas de processus externe (comme la réponse acceptée) et n'exécutera pas les commandes dans un sous-shell supplémentaire (comme l'autre réponse).Comme nous obtenons quelques vues régulières, il est probablement bon de donner une alternative à
eval
cela qui plaira à tout le monde, et a tous les avantages (et peut-être même plus!) De ce rapideeval
"truc". Utilisez simplement une fonction! Définissez une fonction avec toutes vos commandes:et l'exécuter avec vos variables d'environnement comme ceci:
la source
eval
.eval
est mal sans comprendre ce qui fait maleval
. Et peut-être que vous ne comprenez pas vraiment cette réponse après tout (et il n'y a vraiment rien de mal à cela). Sur le même plan: diriez-vous quels
c'est mauvais parce quefor file in $(ls)
c'est mauvais? (et oui, vous n'avez pas dévalorisé la réponse acceptée, et vous n'avez pas laissé de commentaire non plus). SO est parfois un endroit si étrange et absurde.eval
eval
parles vraiment comme un gars qui a déjà lu est mal sans comprendre de quoi il s'agit , je me réfère à ta phrase: cette réponse manque de tous les avertissements et explications nécessaires quandeval
tu parles .eval
n'est ni mauvais ni dangereux; pas plusbash -c
.eval
. Dans la réponse, à condition que les arguments aient été cités, protégeant contre l'expansion variable, je ne vois donc aucun problème avec la réponse.eval
est un problème de sécurité en général (commebash -c
mais moins évident), donc les dangers doivent être mentionnés dans une réponse proposant son utilisation. Les utilisateurs imprudents peuvent prendre la réponse (FOO=bar eval …
) et l'appliquer à leur situation afin qu'elle pose problème. Mais il était évidemment plus important pour le répondeur de déterminer si j'avais rétrogradé ses réponses et / ou d'autres réponses que d'améliorer quoi que ce soit. Comme je l'ai écrit auparavant, l'équité ne devrait pas être la principale préoccupation; être pas pire que toute autre réponse donnée est également sans importance.Utilisez
env
.Par exemple
env FOO=BAR command
,. Notez que les variables d'environnement seront à nouveau restaurées / inchangées une fois l'command
exécution terminée.Faites juste attention à ce que la substitution de shell se produise, c'est-à-dire que si vous voulez référencer
$FOO
explicitement sur la même ligne de commande, vous devrez peut-être l'échapper afin que votre interpréteur de shell n'effectue pas la substitution avant son exécutionenv
.la source
Utilisez un script shell:
la source
export
; sinon$FOO
sera une variable shell, pas une variable d'environnement, et donc pas visible poursomecommand
ousomecommand2
.