3

I have a parent script

while read cmd 
do
  nohup ./script ${cmd[@]} &>> log &
done < ~/list 

that executes this child script

while true
do 
  eval "${CMD[@]}"
  #${CMD[@]}
  #./panic
done

with this list of commands

node ~/www/splash/app.js
node ~/www/splash-two/app.js

When the child script calls eval ${CMD[@]} it executes the way I expect running that command with no complaints but when I try to remove the eval and run the command using ${CMD[@]} it throws the error:

Error: Cannot find module '/home/rumplefraggle/SYS/RABBOT/~/www/splash/app.js'

Now I thought possibly this had something to do with the node command so I tried to execute
ls ~
as the command and it throws the error that ~ can not be found.

Echoing ${@} and not running it expands as I would expect it to.

Also manually inserting the command into the child script also works as expected

I don't understand why eval works and simply running the command using ${@} does not. What is causing ${@} to not expand the ~?

Why is node appending the directory name to the command when ${@} is used?

  • 2
    by the way: read cmd reads an entire line as a single string, and assigns that string to cmd. So it makes little sense to use ${cmd[@]}; cmd is not an array, so you might as well just use $cmd. If you want read to read into an array, use read -a. Also, you almost always want read -r. help read for more info. – rici Jul 9 '13 at 18:26
3

This is because of tilde expansion. The eval expands the tilde, which is replaced with the full path to the home directory. Without it, the command gets a literal tilde passed, and tries to use a relative path (that doesn't exist).

$ echo ~
/home/chris
$ echo "~" 
~
$ eval 'echo ~' 
/home/chris 
  • Didn't you mean eval 'echo ~' or eval "echo ~"? Or even eval echo "~"? As typed, it will produce output ~ – rici Jul 9 '13 at 18:21
  • I see and the error is reporting the full path! Its not actually the command being executed just an artifact in the error report. I need to dig more into the expansion and why it expands in eval an not on the path – Arcabard Jul 9 '13 at 19:04
  • @rici Thanks, my bad, I was typing this out from my phone. – Chris Down Jul 10 '13 at 3:37
0

You need quotes: "${cmd[@]}"

Without the quotes, all the elements of the array are smushed up into a single string. With quotes, each element will be properly handled individually.

From the manual:

If the subscript is ‘@’ or ‘*’, the word expands to all members of the array name. These subscripts differ only when the word appears within double quotes. If the word is double-quoted, [...] ${name[@]} expands each element of name to a separate word.

  • Correct, but that's not what the question is about. – Gilles Jul 9 '13 at 20:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.