PDA

View Full Version : A bash question



lehe
07-28-2009, 10:04 AM
Hi,
I am trying to redirect my output to a file and need to first put a command into a string. Here is the error:


bash-3.2$ cc="(date && time ls -l -a && date) > ./tmp/log"
bash-3.2$ $cc
bash: (date: command not found

What's wrong?
Thanks and regards!

tabstop
07-28-2009, 10:10 AM
I'm not aware of a command called (date either.

What are you trying to use the parentheses for, exactly?

lehe
07-28-2009, 10:11 AM
The reason of using the parentheses is that I want to execute


date && time ls -l -a && date

and make its output redirected to file ./tmp/log

Salem
07-28-2009, 10:18 AM
old-school, you use back-ticks


cc=`date && time ls -l -a && date`


new-school, I think it's something like


cc=$(date && time ls -l -a && date)

tabstop
07-28-2009, 10:25 AM
Back-ticks execute the command and store the result in the variable. So if you tried to then execute $cc you'd get things like "Tue: command not found".

I can get parentheses to work when I type them straight on the command line, but not inside a variable like that. More research is needed.

Brafil
07-28-2009, 10:34 AM
$() is the same as ``. But better, since easier to read (and for me, to type) and can't mix up with ''.

Kennedy
07-28-2009, 10:54 AM
Hi,
I am trying to redirect my output to a file and need to first put a command into a string. Here is the error:


bash-3.2$ cc="(date && time ls -l -a && date) > ./tmp/log"
bash-3.2$ $cc
bash: (date: command not found

What's wrong?
Thanks and regards!

What you did is okay, but I think when you want to "run" a variable, you have to eval it:
eval $cc. . . but I cannot recall at the moment. It is worth a try.

MK27
07-28-2009, 12:04 PM
Hi,
I am trying to redirect my output to a file and need to first put a command into a string.

You will have to redirect each command before &&. However, you cannot effectively run a string with && in it anyway.

One option is to put this into an array, which maybe is what you were trying to do with the brackets before, since that is what they'll do:


cc=('date' 'bash -c "time ls -l"' 'date')

The reason I used bash -c "time ls -l" is because time is a bash builtin, and if you try to run it from a variable this way you will get
bash: time: No such file or directory
Now here's a weird thing about bash. If you do this:


for e in ${cc[@]}; do echo $e; done

You will get this:
date
bash
-c
"time
ls
-l"
date
It seems an element here is not really what one might hope. However, this works:


for e in 0 1 2; do echo ${cc[$e]}; done

date
bash -c "time ls -l"
date
So, it looks like all we need now is:


for e in 0 1 2; do ${cc[$e]}>>tmp.txt; done

Which will work (...almost) and amounts to (almost) same thing as using &&. I say almost because in fact you get a strange parsing related error, again from the bash/time/ls construct:
ls: -c: line 0: unexpected EOF while looking for matching `"'
ls: -c: line 1: syntax error: unexpected end of file
Since the next "e" does execute dispite the failure of ${cc[1]}, this is not really equivalent to an && -- for that you need to get more complicated.

But I cannot get 'bash -c "time ls"' to run this way. Non builtins with parameters are fine.

I'll go ask some other bunch of monkeys tho and see if they have anything wise to add.

tabstop
07-28-2009, 09:45 PM
((stuff))
Or you can use eval. (Thanks Kennedy for getting my one new thing for today out of the way early so I could relax!)

MK27
07-29-2009, 12:43 AM
Or you can use eval.

Didn't know bash had an eval. That simplifies that.

One last thing: to get the output of "time" into the file:


cc="date && time ls -d && date"
eval $cc >tmp.txt 2>tmp.txt

since it appears on stderr (aka channel 2).