Take the 2-minute tour ×
Ask Different is a question and answer site for power users of Apple hardware and software. It's 100% free, no registration required.

I realized that the "say" command can be great when combined with another command/program because it can read you the output. I tried to pipe the output from "leave" to "say" by typing the following in terminal, but it didn't work.

leave +5 | say

What is the correct way to do this?

share|improve this question
    
Based off of very initial analysis, I don't think you'll be able to, because leave forks/daemonizes and leaves your shell. –  Jason Salaz Mar 6 '11 at 4:38
    
So you can't pipe output from daemons to another program? –  styfle Mar 6 '11 at 5:45
    
You can probably capture the output of daemons and pipe it to another program, but not as simply as | –  user588 Mar 6 '11 at 5:49
add comment

4 Answers

up vote 4 down vote accepted

Based on mankoff's answer, this works:

leave +1 2>&1 | while read line ; do echo $line | say ; done

although leave no longer vanishes into the background and lets you carry on typing. Similarly:

leave +1 2>&1 | while read line ; do echo $line | say ; done &

will make it vanish into the background, but will also speak a (harmless) process ID number as well. So neither is quite perfect, but both work.

(I was looking for a solution to:

ping google.com | say

which suffers a similar problem, and someone suggested the above as a solution. I didn't add this as a comment to mankoff's answer because I can't work out how to put spaces and newlines in comments.).

share|improve this answer
    
You can't put newlines in comments. Unfortunately. –  Jason Salaz Mar 8 '11 at 1:11
    
you could edit my answer, but I think your comments are worthy of their own 'answer'. To silence the process ID, perhaps something before |say like |grep -v ^[0-9]*$, etc. –  user588 Mar 9 '11 at 17:58
    
Thanks that worked. I'm guessing read line reads each line of an input and then you just echo the line so you can pipe it to say? –  styfle Mar 11 '11 at 3:57
    
Yes, and the while ... do form makes sure it does the read line/say line pair over and over. (The problem is that when you pipe input into say, it waits until the entire end of the input before speaking all of it at once, however read takes one line and stops. So the code chops a continuous output into line-sized chunks and launches say once for each chunk). –  TessellatingHeckler Mar 12 '11 at 2:06
add comment

I think you simply can´t use leave for that, rather use sleep with the correct amount of seconds (put it into a short script to convert seconds to minutes, hours):

sleep 60 && say -v Vicki 'Time to leave!' &
share|improve this answer
    
That is an interesting solution although The question was not how to make the computer say Time To leave; I want to know how to pipe output from one program to say. Thanks for the response though. –  styfle Mar 6 '11 at 2:13
add comment

Your example is, in general, the correct way to pipe normal output to say:

 cat file | say
 echo "hello world" | say

The specific issue is that the | (pipe) character transfers STDOUT from the command on the left to STDIN to the command on the right. say then speaks whatever is on STDIN.

However, leave does not print the output directly to STDOUT. It is either using STDERR, or some other message mechanism. You can pipe STDERR through the |, but the syntax is shell dependent. For bash, you would do it like so, although I'm not sure that this will make leave work with say, as I don't much about leave.

cmd 2>&1 |cmd2
share|improve this answer
    
STDERR or some other message mechanism? Why would it do that. Another commenter seems to think the issue is that leave is a daemon. What is that last command you wrote? cmd 2>&1 |cmd2 –  styfle Mar 6 '11 at 6:45
    
The last command pipes STDOUT and STDERR through the pipe. Normally only STDOUT gets captured, and STDERR goes wherever the first command would send it. Why would leave do that (whatever "that" is)? Because the authors wrote it that way. –  user588 Mar 6 '11 at 6:49
    
I used that command to pipe STDERR from leave to say and it almost worked. Basically, all of the output was sent at one time rather than in increments. –  styfle Mar 6 '11 at 7:35
add comment

As an addition to this - if you want to pipe an ongoing file to say, the "recipe" also works with tail:

tail -f ~/Documents/activity.log | while read line ; do echo $line | say ; done
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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