Lucas Alanis
Lucas Alanis

Reputation: 1278

Why does this R script not work when called from this bash script?

I have the following R script for which I have added comments to make a simple example with cars of what I am trying to achieve:

#!/usr/bin/env Rscript

# the arguments come in this way: 
# args[1] is a file containing the maximum speeds of different cars (one per line) 
# args[2] is the title that the plot will have
# args[3] contains the horsepower of the engine of the first car in args[1] (the lowest)
# args[4] contains the horsepower of the engine of the last car in args[1] (the highest)
# NOTE1: the speeds in args[1] must be listed starting from the car 
# with the lowest horsepower to the car with the highest horsepower 
# NOTE2: in args[1], a car must differ from the next one by 1 horsepower, i.e., if
# there are 5 speeds, and the horsepower of the first car in the file is 30, then the 
# the horsepower of the second one must be 31, the third one 32, .... the fifth one must
# be 34.


args<-commandArgs(TRUE)

# creating the vector with the horsepower of each car

horsepowers = numeric()

for (i in args[3]:args[4]) {

        horsepowers = c(horsepowers,i)

}

# reading file with speeds and getting vector with speeds

speeds <- read.csv(file=args[1],head=FALSE,sep="\n")$V1

# creating plot with speeds in previous vector

outputTitle = gsub(" ","", args[2] , fixed=TRUE)

pdf(paste(outputTitle, ".pdf", sep = ""))

plot(horsepowers, speeds, type="o", col="red", xlab="horsepowers", ylab="speeds")

# giving a title to the plot

title(main=args[2], col.main="Black")

I have a sample file called myFile with speeds of 5 cars that looks like this

150
156
157
161
164

And suppose that the horsepower of the first car is 30 so that would make the horsepower of the last car 34 (remember that the first speed corresponds to the car with the lowest horsepower, the second one to the car with the next to lowest horsepower, and so on; and the cars must differ by 1 horsepower, otherwise the for loop in the script would not make sense). So if I run the script in the command line like this:

./myPlotter.R myFile "My Title" 30 34

it works fine and makes the plot (I cropped the y label, x label, and title just because they don't match with the car example above but the script used is the same, I just changed the variable names for the car example):

However, when called from the following bash script:

#!/bin/bash

while getopts ":a:1:2:3:4" arg; do

case "$arg" in

a)
    option=$OPTARG
    ;;
1)
    fileWithSpeeds=$OPTARG
    ;;
2)
    titleOfGraph=$OPTARG
    ;;
3)
    lowestHP=$OPTARG
    ;;
4)
    highestHP=$OPTARG
    ;;

esac

done

# I do not think that this if statement makes any difference for this example
# but I left it there just in case

if [ $option == "option1" ]; then

        ./myPlotter.R $fileWithSpeeds $titleOfGraph $lowestHP $highestHP

fi

in this way:

./bashPlot.sh -a option1 -1 myFile -2 "My Title" -3 30 -4 34

I get the following error:

Error in args[3]:args[4] : NA/NaN argument
Execution halted

What is causing this?

Summary: I have an R script that works fine when called from the command line but gives an error when called from a bash script with arguments gotten from getopts.

Upvotes: 1

Views: 116

Answers (1)

janos
janos

Reputation: 124734

The bug is in the getots string, instead of this:

while getopts ":a:1:2:3:4" arg; do

It should be like this:

while getopts "a:1:2:3:4:" arg; do

You could see the problem by echoing the command that executes the R script:

echo "./myPlotter.R $fileWithSpeeds $titleOfGraph $lowestHP $highestHP"
./myPlotter.R $fileWithSpeeds $titleOfGraph $lowestHP $highestHP

You could see from the output that the $highestHP parameter was always blank.

Extra tips

You don't need the double quotes here:

if [ $option == "option1" ]; then

And the [ ... ] operator is now obsoleted, use [[ ... ]] instead, like this:

if [[ $option == option1 ]]; then

Upvotes: 2

Related Questions