Search code examples
bashshellcurldouble-quotessingle-quotes

Curl command in bash script using variables


I have a curl command that looks like this:

curl -X PUT -H "myheader:coca-cola" -d '{ "name":"harrypotter" }' http://mygoogle.com/service/books/123

Running this command as is via terminal returns the expected results.

I am trying to incorporate this curl command in my bash script as follows:

#!/bin/bash

MYURL=http://mygoogle.com/service/books/123

# Generate body for curl request
generate_put_data()
{
  cat <<EOF
{
  "name":"harrypotter"
}
EOF
}

put_data=$(echo "$(generate_put_data)")
put_data_with_single_quotes="'$put_data'"

# Generate headers for curl request
header=myheader:coca-cola
header_with_double_quotes="\"$header\""

# The following function takes two inputs - a simple string variable (with no spaces or quotes) and the curl command string
function run_cmd() {
  echo $1
  echo $2

  #Run the curl command
  "$2"

  #Check return code of the curl command
  if [ "$?" -ne 0 ]; then
    #do something with simple string variable
    echo "$1"
    echo "Job failed"
    exit 1
  else
    #do something with simple string variable
    echo "$1"
    echo "Job Succeeded"
  fi
}

# Run the bash function - run_cmd

run_cmd "mysimplestring" "curl -X PUT -H $header_with_double_quotes -d $put_data_with_single_quotes $MYURL"

However, when I try to run the above bash script, it fails at the point where I call run_cmd() function with the two inputs. I get the following error:

curl -X PUT -H "myheader:coca-cola" -d '{
  "name":"harrypotter"
}' http://mygoogle.com/service/books/123: No such file or directory
Job failed

This error occurs on the line where "$2" is being executed in the run_cmd() function declaration.

Could someone help me understand where I am going wrong? Thanks!


Solution

  • "$2"
    

    This will take the second argument and try to run it without doing any word splitting. It treats it as one string.

    You're going to run into trouble passing in the curl command as one string. You'll do better if you pass it without quotes, just as if you typed it on the command line. You'll want to quote each of the variables but not quote the command as a whole.

    run_cmd "mysimplestring" curl -X PUT -H "$header" -d "$put_data" "$MYURL"
    

    Notice that you don't need the "with_quotes" variables any more. You don't have to do anything like that. The original plain values will work.

    Now you can access the command using array syntax:

    function run_cmd() {
      local name=$1; shift
      local cmd=("$@")
    
      #Run the curl command
      "${cmd[@]}"
    }
    

    By the way, this is a useless use of echo:

    put_data=$(echo "$(generate_put_data)")
    

    Make that:

    put_data=$(generate_put_data)