Je connais bien l' utilitaire source
(aka .
), qui prendra le contenu d'un fichier et l'exécutera dans le shell actuel.
Maintenant, je transforme du texte en commandes shell, puis je les exécute, comme suit:
$ ls | sed ... | sh
ls
est juste un exemple aléatoire, le texte original peut être n'importe quoi. sed
aussi, juste un exemple pour transformer du texte. Le peu intéressant est sh
. Je pipe tout ce que je suis arrivé sh
et il le fait fonctionner.
Mon problème est que cela signifie démarrer un nouveau sous-shell. Je préfère que les commandes soient exécutées dans mon shell actuel. Comme je pourrais le faire avec source some-file
, si j'avais les commandes dans un fichier texte.
Je ne veux pas créer de fichier temporaire car je me sens sale.
Sinon, j'aimerais démarrer mon sous-shell avec exactement les mêmes caractéristiques que mon shell actuel.
mise à jour
Ok, les solutions utilisant le backtick fonctionnent certainement, mais je dois souvent le faire pendant que je vérifie et modifie la sortie, donc je préférerais de loin s'il y avait un moyen de canaliser le résultat dans quelque chose à la fin.
triste mise à jour
Ah, la /dev/stdin
chose avait l'air si jolie, mais, dans un cas plus complexe, cela n'a pas fonctionné.
Donc, j'ai ceci:
find . -type f -iname '*.doc' | ack -v '\.doc$' | perl -pe 's/^((.*)\.doc)$/git mv -f $1 $2.doc/i' | source /dev/stdin
Ce qui garantit que tous les .doc
fichiers ont leur extension en minuscule.
Et qui, d'ailleurs, peut être manipulé xargs
, mais ce n'est pas le problème.
find . -type f -iname '*.doc' | ack -v '\.doc$' | perl -pe 's/^((.*)\.doc)$/$1 $2.doc/i' | xargs -L1 git mv
Donc, quand je lance le premier, il se termine tout de suite, rien ne se passe.
Réponses:
$ ls | sed ... | source /dev/stdin
MISE À JOUR: Cela fonctionne dans bash 4.0, ainsi que tcsh et dash (si vous passez
source
à.
). Apparemment, c'était buggy dans bash 3.2. À partir des notes de publication de bash 4.0 :la source
eval "$(sed ...)"
approche - mais merci pour le heads-up 3.2 bug!La
eval
commande existe précisément dans ce but.eval "$( ls | sed... )"
En savoir plus sur le manuel bash :
la source
eval "$( ssh remote-host 'cat ~/.bash_profile' )"
Notez que j'utilise bien bash 3.2.Wow, je sais que c'est une vieille question, mais je me suis retrouvé avec le même problème exact récemment (c'est comme ça que je suis arrivé ici).
Quoi qu'il en soit - je n'aime pas la
source /dev/stdin
réponse, mais je pense que j'en ai trouvé une meilleure. C'est trompeusement simple en fait:echo ls -la | xargs xargs
Bonne droite? En fait, cela ne fait toujours pas ce que vous voulez, car si vous avez plusieurs lignes, cela les concatera en une seule commande au lieu d'exécuter chaque commande séparément. Donc, la solution que j'ai trouvée est:
l'
-L 1
option signifie que vous utilisez (au plus) 1 ligne par exécution de commande. Remarque: si votre ligne se termine par un espace de fin, elle sera concaténée avec la ligne suivante! Assurez-vous donc que chaque ligne se termine par un non-espace.Enfin, vous pouvez faire
pour voir quelles commandes sont exécutées (-t est détaillé).
J'espère que quelqu'un lit ça!
la source
Essayez d'utiliser la substitution de processus , qui remplace la sortie d'une commande par un fichier temporaire qui peut ensuite être récupéré:
source <(echo id)
la source
echo <(echo id)
/dev/fd/12
cat <(echo id)
id
source <(echo id)
id
(...)
redirigé?Je pense que c'est "la bonne réponse" à la question:
ls | sed ... | while read line; do $line; done
Autrement dit, on peut faire une
while
boucle; laread
commande commande prend une ligne de sonstdin
et l'affecte à la variable$line
.$line
devient alors la commande exécutée dans la boucle; et il continue jusqu'à ce qu'il n'y ait plus de lignes dans son entrée.Cela ne fonctionnera toujours pas avec certaines structures de contrôle (comme une autre boucle), mais cela correspond à la facture dans ce cas.
la source
Je sorte de sensation comme
ls | sed ... | source -
serait plus joli, mais malheureusement ,source
ne comprend pas-
signifierstdin
.la source
Je pense que votre solution est la substitution de commandes avec des backticks: http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html
Voir section 3.4.5
la source
$( )
syntaxe peut être préférée. 'Course backticks work in more shells ...Pour utiliser la solution de mark4o sur bash 3.2 (macos), une chaîne here peut être utilisée à la place des pipelines comme dans cet exemple:
. /dev/stdin <<< "$(grep '^alias' ~/.profile)"
la source
Pourquoi ne pas l'utiliser
source
alors?$ ls | sed ... > out.sh ; source out.sh
la source