Stephane Chazelas wrote:
> On Mon, 18 Sep 2006 16:37:06 +0100, SiKing wrote:
>> Hi all,
>> I was wondering if someone could lend me an explanation. :)
>> I am working in gnu-bash, version 3.
>> I have a list of commands (scripts, written in various scripting languages) in a
>> text file, that my script reads in one at a time, and then I try to execute.
>> What is the difference between the following ways of executing these:
>> $executable
>> `$executable`
>> eval $executable
>> The first and the third do what I want, but I am not sure why. The second (my
>> first attempt) did not work correctly.
>> Any insight is appreciated.
> [...]
> 1 - $executable
> When you leave a variable unquoted in that context (i.e. a
> simple command arguments), it has a very special (and complex)
> meaning.
> The shell will first split the variable content into a list of
> words using a complex algorithm that involves the $IFS special
> variable.
> With the default value of $IFS, it will split it on blanks
> (discarding the leading and trailing blanks and considering a
> *sequence* of blanks as a single instance of the separator).
> For instance " foo<Tab> a* baz" will be split into the 3 words
> "foo", "a*", "baz".
> Then it expands patterns in them (a bit as it would do if you
> typed them on the command line but not exactly).
> So the "a*" above will be expanded into the list of files in the
> current directory whose name starts with a "a".
> The command to run will be derived from the first argument
> resulting from that splitting, and that first argument will also
> be used as the argv[0] of the command being run.
> 2 `$executable`
> First `cmd` (aka $(cmd)), means run the cmd command, collect its
> (and all its children's) output and once the command terminates
> and every one of its child processes has closed its stdout (or
> terminated), then use the collected output to build a list of
> argument for another command, that building of arguments is done
> the same way as described above for the expansion of
> $executable.
> For instance
> `echo ls -ld -- '*.txt'`
> with the default value of IFS, would collect the output of echo:
> "ls -ld -- *.txt\n", remove the trailing newline, split it into
> the words "ls", "-ld", "--", the list of txt files in the
> current directory, would derive the "/bin/ls" command to be run
> from that and would pass the /bin/ls command the list of words
> above as arguments.
> So
> `$exectable`
> would first do what is described in 1- above, then collect the
> output of the command derived from the first resulting in the
> splitting of $executable. And use that output to build another
> list of arguments from which the first one will be used to
> derive another command to be run.
> 3- eval $executable
> $executable is split as in 1-. Except that the list of arguments
> is now prepended with "eval", so the command to be run will be
> "eval" instead of the first word resulting from the
> splitting/wildcard expansion of $executable.
> And eval concatenates its arguments with spaces and evaluates
> the result as shell code.
> I would say as neither of the 1, 2, 3 above is a correct way to
> go. The correct way (but that depends on what $executable is
> meant to contain) would be
> 4- eval "$executable"
> Some examples.
> With the default value of $IFS, with
> executable='echo "ls \"foo * \""'
> With 1- it will run the echo command with those arguments:
> <<echo>>, <<"ls>>, <<\"foo>>, the list of files in the current
> directory, <<\"">>, so will output:
> "ls \"foo <the-list-of-files> \""
> With 2-, it will run the same echo command, and then try and
> find a command called <<"ls>> and will probably fail.
> With 3-, it will run the
> echo "ls \"foo <the-list-of-files> \""
> command which should (unless there are shell special characters
> in the list-of-files) output:
> ls "foo <the-list-of-files> "
> With 4-, it should run the
> echo "ls \"foo * \""
> command, so should output:
> ls "foo * "
> And eval "$(eval "$executable")" should do that and then run the
> ls "foo * " command, so list the file called "foo * ".
Thank You for the explanation. I had to print this out, and take it home for the Thanx.