Karthik Karthik - 3 months ago 14
Bash Question

Shell: Difference between eval and ksh commands

Inside my shell script, i am calling another script which is used for ftping the file. currently it is as below:

eval doftp.sh -1 '"File Name with spaces.txt"'


If the file name has spaces between them it does not work. But if i do changes as below, it works.

ksh doftp.sh -1 '"File Name with spaces.txt"'


So what was issue with eval command.I need the file name to go with double quotes. If i am not wrong, i need to escape the spaces with eval command and thats where i am going wrong i believe. Please confirm.

Answer

First, of course, "eval" can do all kinds of things apart from what's going on here. It instructs the shell to re-evaluate its arguments. So for instance, you could do things like this:

b=4
a='b'
eval "$a=3"
echo $b    # yields 3

This also means "eval" is a bit dangerous by nature, because it will run whatever command it's given.

a='rm -rf /;b'
eval "$a=3"    #Removes all your files and sets b=3

In this case, it seems "eval" is just stripping off some quotes.

eval doftp.sh -1 '"File Name with spaces.txt"'
# is equivalent to:
doftp.sh -1 "File Name with spaces.txt"

Running a shell with a shell script as its argument is equivalent to just running the shell script. It doesn't re-process the arguments - which means something in that shell script probably requires those quotes. (Given that it's called "doftp", maybe it's feeding the quoted string as an argument to "get" or "put" in an FTP client.)

If you had a shell script "args.sh" that printed the arguments you gave to it, for instance:

# args.sh
while [ "$#" -gt 0 ]; do echo "$1"; shift; done

And you ran it like you're running "doftp.sh", this is what you'd see:

$ ./args.sh unquoted '"String with     spaces"'
unquoted
"String with     spaces"
$ ksh ./args.sh unquoted '"String with     spaces"'
unquoted
"String with     spaces"

The shell you're running the command in strips off the single quotes, but feeds the string contained in those single quotes as a single argument to the command you're running. "eval" could then be used to do that again:

$ eval ./args.sh unquoted '"String with     spaces"'
unquoted
String with     spaces

...but apparently that's not what you want here. When ksh gets the string as one of its arguments, it maintains that string as-is unless you subject it to word splitting or something.