If I had a running process like tail -F watch.txt and I wanted to capture the stdout from this running process and pipe it to another command on stdout how could this be done?

Here's an example of a running process.

$ tail -F watch.txt

Let's say I wanted to capture the stdout and write each of these a new file or process each string with another command. For instance there's this terminal-notifier (mac specific) command that takes a message terminal-notifier --message "$STDOUT_FROM_TAIL".

Is this possible with things that already exist within unix?

  • Since it is already running, you might have to redirect the file descriptor of that process elsewhere. Try: ingvar.blog.redpill-linpro.com/2010/07/10/… – muru Dec 11 '14 at 23:54
  • If the problem is to call terminal-notifier for each new line that tail -f reports, have a look at xargs – Jasper Dec 11 '14 at 23:56

Assuming you can restart the program and put it in a pipe, you can then pipe it to xargs, with the following caveats:

  • you want to run the command one line at a time (-n 1)
  • you want to put the output inside a parameter (-i)
  • you probably want the message to run as soon as the tail reports it, so you need tail to be line buffered.

Depending on what you have installed:

stdbuf -o 0 tail -f FILE | xargs -i -n 1 terminal-notifier --message "{}"

unbuffer    tail -f FILE | xargs " "

and I saw a tailf version that supported the -l (line-buffered) option.

You can also emulate tail -f in Perl.

And you can replace xargs (even if it's pretty standard and ubiquitous) with a specially crafted for loop in the shell (it's not as simple as it looks, though; it's similar to processing filenames with spaces in a loop).

If you cannot restart the program, you need to intercept its stdout. Here's a Stack Overflow answer about that. Other utilities and scripts such as reredirect are described here; I don't know about their compatibility with MacOS, though.

Further modifications

The output can be parsed normally with utilities such as sed or cut:

unbuffer tail -f FILE | grep animal | sed -e 's/animal (.*) gear/\1/' | xargs ...

This way we would have:

Output by tail                      output by grep        output by sed
correct horse battery staple
animal rhino gear                   animal rhino gear     rhino
llama is animal                     llama is animal       llama is animal
llama peruvian                      
animal ant gearbox                  animal ant gearbox    antbox

(--line-buffered option to grep may be used)

| improve this answer | |
  • I can restart the program. However I'm on mac and don't have stdbuf or unbuffer installed. Should I install one of those or is there another alternative caked into OSX? – ThomasReggi Dec 12 '14 at 0:56
  • Do you have Perl installed? I can amend the answer tomorrow morning. – LSerni Dec 12 '14 at 1:12
  • Just got stdbuf installed but I'm getting xargs: illegal option -- i ideas? – ThomasReggi Dec 12 '14 at 2:23
  • I don't have a Mac, but check with xargs -h or --help how to set up a replacement pattern. Could be -R "{}" for example. – LSerni Dec 12 '14 at 6:48
  • echo a b c d e f | xargs -I letter -n 1 terminal-notifier -message letter I got this example to work :) – ThomasReggi Dec 12 '14 at 7:01

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.