1

I have .sh file that I would like to dotsource into my running environment. This does not work:

curl -s https://raw.githubusercontent.com/bla/bla/master/stuff.sh | bash

The above does not work, i.e. The script runs, but the environment variables and things inside stuff.sh are not dotsourced into the running environment. I also tried:

. curl -s https://raw.githubusercontent.com/bla/bla/master/stuff.sh | bash
curl -s https://raw.githubusercontent.com/bla/bla/master/stuff.sh | bash source
curl -s https://raw.githubusercontent.com/bla/bla/master/stuff.sh | source bash

All fail. Would appreciate knowing how this can be done?

phuclv
  • 37,963
  • 15
  • 156
  • 475
YorSubs
  • 3,194
  • 7
  • 37
  • 60
  • 2
    Use `source <(command)` – kvantour Nov 22 '20 at 11:54
  • Thanks, but can't seem to get that to work: `$ source < (curl -s https://raw.githubusercontent.com/user/bla/master/stuff.sh | bash) => bash: syntax error near unexpected token `('` `$ source < (curl -s https://raw.githubusercontent.com/user/bla/master/stuff.sh) => bash: syntax error near unexpected token `('` `$ source < curl -s https://raw.githubusercontent.com/user/bla/master/stuff.sh | bash => bash: curl: No such file or directory`` – YorSubs Nov 22 '20 at 11:58
  • 1
    There should be no space between < and ( – kvantour Nov 22 '20 at 12:16

2 Answers2

1

I am not a bash expert, but if you are willing to accept some drawbacks, the easiest method to do that is without pipes. I believe that it should be possible when you separate download and sourcing:

prompt># curl -s https://raw.githubusercontent.com/bla/bla/master/stuff.sh > ./stuff.sh
prompt># . ./stuff.sh

From the bash manual (man bash), in the chapter about the builtin source command:

Read and execute commands from filename [...]

There is no mentioning about standard input as a possible source for the commands which should be sourced.

However, as hanshenrik stated in his answer, you always can use process substitution to create a temporary (and invisible on the file system) file which you can feed to source. The syntax is <(list), where <(list) is expanded to a unique file name chosen by bash, and list is a sequence of commands whose output is put into that file (the file does not appear on the file system, though).

Process substitution is documented in the bash manual (man bash) in a paragraph under that exact caption.

Binarus
  • 4,005
  • 3
  • 25
  • 41
  • ok, great, I was (wrongly) thinking that I might have to chmod the file after downloading it before I could run it, but this works. Perfect. – YorSubs Nov 22 '20 at 12:03
  • 1
    kvantour's solution is better, this approach has drawbacks: what happens if you have another script which is also using the filename "stuff.sh" for something? this will delete some other script. or what happens if the filesystem is read-only for some reason? this will fail. kvantour's solution won't delete anything, and will work even if it's a read-only filesystem – hanshenrik Nov 22 '20 at 12:55
  • 1
    I believe that it depends on circumstances which solution is better. For example, chances are that the OP needs that file not only one time; then having it stored would be better than downloading it again and again. – Binarus Nov 22 '20 at 13:01
  • I want to do all of this actually, there are times that I want to overwrite the file and times that I'll do a `[ -f ./file ]` to check and times I just want to create without creating a file at all, so all very helpful thanks. – YorSubs Nov 22 '20 at 15:08
1

try

source <(curl -s https://raw.githubusercontent.com/bla/bla/master/stuff.sh)

i tried doing

curl -s https://raw.githubusercontent.com/bla/bla/master/stuff.sh | source /dev/stdin

but that didn't work for some reason, no idea why (anyone knows?)

hanshenrik
  • 19,904
  • 4
  • 43
  • 89
  • 1
    For future readers, the construct shown first in this answer is called *process substitution* and is documented in the bash manual (`man bash`) in a paragraph with exactly that caption. – Binarus Nov 22 '20 at 13:13
  • 1
    The second contruct does not work because `source /dev/stdin` is run in a subshell. – Philippe Nov 22 '20 at 16:30