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?

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

4 Answers 4


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.).

  • You can't put newlines in comments. Unfortunately. Commented Mar 8, 2011 at 1:11
  • 1
    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
    Commented Mar 9, 2011 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
    Commented Mar 11, 2011 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). Commented Mar 12, 2011 at 2:06

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
  • 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
    Commented Mar 6, 2011 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
    Commented Mar 6, 2011 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
    Commented Mar 6, 2011 at 7:35

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

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!' &
  • 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
    Commented Mar 6, 2011 at 2:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .