Bash – curl outfile variable not working in bash script

bashcurlshell-script

Attempting to shorten a bash script that uses curl to fetch multiple API calls takes something like this:

curl --user $USER:$PASS https://api.example.com/foo -o 'foo.json'
curl --user $USER:$PASS https://api.example.com/bar -o 'bar.json'
curl --user $USER:$PASS https://api.example.com/baz -o 'baz.json'

And use it in this form:

curl --user $USER:$PASS https://api.example.com/{foo,bar,baz} -o '#1.json'

The issue is that curl is fetching foo, bar and baz but is not assigning the output to foo.json, bar.json and baz.json. It is literally creating #1.json and piping output to stdout. Has been tried with single, double, and no quotes, all same result.
This is being run inside a bash script, although the curl command behaves the same way when entered directly on the command line. Is this an OS X syntax issue?

Best Answer

Your problem is that the {...} expression is also valid shell syntax. For example, run:

echo file/{one,two}

And you get:

file/one file/two

So when you run:

curl --user $USER:$PASS https://api.example.com/{foo,bar,baz} -o '#1.json'

The {foo,bar,baz} is getting interpreted by your shell, and curl actually receives the command line:

  curl --user youruser:secret https://api.example.com/foo https://api.example.com/bar https://api.example.com/baz -o '#1.json'

Since curl doesn't see the {...} expression, you don't get the magical handling for #1. The solution is simply to enclose the URL in single quotes:

curl --user $USER:$PASS 'https://api.example.com/{foo,bar,baz}' -o '#1.json'

The single quotes inhibit any shell expansion of the string.

Related Question