Reputation: 533
I'm trying to execute the following command (which works on the terminal) within Java:
awk -F';' 'NR>1{gsub(/; +/,";",$0);printf("{msisdn:\"%s\",imei:\"%s\",brand:\"%s\",model:\"%s\",sap:\"%s\",sap_cod:\"%s\",file_name:\"teste\",company:{\"$ref\":\"company\",\"$id\":ObjectId\"456\")}}\n",$2,$15,$16,$17,$18,$20)}' /Users/milena/Desktop/giant.csv
The Java code I am using is this:
String fileName = "test";
String company = "456";
String awk = "awk -F';' 'NR>1";
String gsub = "{gsub(/; +/,\";\",$0);";
String printf = "printf(\"{msisdn:\\\"%s\\\",imei:\\\"%s\\\",brand:\\\"%s\\\","
+ "model:\\\"%s\\\",sap:\\\"%s\\\",sap_cod:\\\"%s\\\",file_name:\\\""+fileName+"\\\",company:"
+ "{\\\"$ref\\\":\\\"company\\\",\\\"$id\\\":ObjectId\\\""+company+"\\\")}}\\n\",$2,$15,$16,$17,$18,$20)}\' ";
String path = "/Users/milena/Desktop/giant.csv";
String command = awk + gsub + printf + path;
Process p
p = Runtime.getRuntime().exec(command);
The error I am getting is:
awk: syntax error at source line 1
context is
>>> ' <<<
missing }
missing )
awk: bailing out at source line 1
Any ideas of what am I doing wrong?
Upvotes: 3
Views: 419
Reputation: 34638
When you use Runtime.getRuntime().exec(command)
, it takes the string and breaks it into a command and arguments based on spaces.
This simple parsing is not the same as the parsing done by the shell when you invoke the command. The shell, for example, takes quotes into consideration. This means that if you have a command line like:
cmd 'abc' 'def'
The arguments that the shell will send to the cmd
command are going to be abc
and def
. But if you give the same command to Runtime.getRuntime().exec(command)
, it will send 'abc'
and 'def'
to cmd
as arguments. Yes, including the quotes!
The situation gets worse if you have spaces in any of the arguments. If the shell gets
cmd 'my single argument'
It will invoke the command with a single argument my single argument
. But Runtime.getRuntime().exec(command)
will invoke cmd
with three arguments: 'my
, single
and argument'
!
So it's not recommended to use this particular overload for anything but very simple commands. Instead, you should use the overload that accepts an array of strings. The first element should be the command name, and each argument should be in a separate element:
String[] command = { "awk",
"-F;",
"NR>1{gsub(/; +/,\";\",$0);printf(\"{msisdn:\\\"%s\\\",...",
"/Users/milena/Desktop/giant.csv"
};
Process p = Runtime.getRuntime().exec(command);
Note: It is recommended to use the ProcessBuilder
class to build a Process
rather than Runtime.getRuntime.exec
- it gives you better control of the command and you can pass the separate arguments right to the constructor.
Upvotes: 3