Mike D
Mike D

Reputation: 6195

How do you source a file (i.e. gist) in bash?

I want to source a gist into my bash shell, how do I do this in one line? In other words, I do not want to create an intermediate file.

I tried this, but it fails to source the remote file:

source <(curl -s -L https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash)

Running on Mac OSX 10.9.

Thanks in advance.

Upvotes: 4

Views: 1183

Answers (3)

Brian Campbell
Brian Campbell

Reputation: 332866

Apple ships an ancient version of Bash, Bash 3.2; Bash 4 was released 5 years ago. Here are a few possible ways to work around this:

  1. Install MacPorts, Homebrew, or pkgsrc and install Bash via one of them; or just build and install it yourself from source. Remember to add your newly installed bash to /etc/shells so you can set it as your shell, then go to "System Preferences > Users and Groups", click the lock to supply your password so you can make changes, then right click (two-finger click/control click) on your user to choose "Advanced Options..." and change your shell there.
  2. If you must be compatible with the 7 year old Bash shipped on OS X, you could just save the file and source it from there. Here's an example Bash function to make that easier:

    function curlsource() {
        f=$(mktemp -t curlsource)
        curl -o "$f" -s -L "$1"
        source "$f"
        rm -f "$f"
    }
    curlsource https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash
    
  3. If you absolutely must avoid even creating a temporary file, and must run on ancient versions of Bash, the best you can do is read into a string and eval the result. I tried to emulate the effect of source <(cmd) by creating a FIFO (named pipe), piping the output of cmd into it, and reading it with source, but got nothing. It turns out, taking a look at the source for Bash 3.2, source simply reads the whole file into a string, and it checks the file size before doing so. A FIFO returns a size of 0 when you stat it, so source happily allocates a string of length 1 (for the trailing null), reads 0 bytes into it, and returns success. So, since source is just reading the whole file into a string and then evaluating that, you can just do the same:

    eval "$(curl -s -L https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash)"
    

Upvotes: 3

user5067592
user5067592

Reputation: 1

This will work on any version of bash and without any file creation.

source <<< "$(curl -s -L https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash)"

Upvotes: -2

chepner
chepner

Reputation: 531325

OS X still ships bash 3.2 by default; in that version, the source command does not seem to work properly with process substitutions, as can be demonstrated with a simple test:

$ source <(echo FOO=5)
$ echo $FOO

$

The same source command does, however, work in bash 4.1 or later (I don't have a 4.0 installation to test, and the release notes seem to be silent on the matter.)

Upvotes: 1

Related Questions