clojurebabashka

How to filter output of tail with babashka


I want to filter and modify output of tail command. This is what I come up with:

#!/usr/bin/env bb

(ns script
  (:require
   [clojure.java.io :as io]
   [clojure.string :as str]
   ))

(->> (line-seq (io/reader *in*)
               (filter #(re-find #"^\[.*CONSOLE" %))
               (map #(str "carpenter " %)))

It works for normal tail. But I want to use it for "tail -f" command. Any ideas?

Thx


Solution

  • This example starts writing to a file two kinds of messages: HELLO and BYE. Then it starts a tail -f process to watch the file and then reads from the output of that process and only captures the BYE lines and prints them with a custom string in front.

    (ns tail-example
      (:require [babashka.process :as p]
                [clojure.java.io :as io]))
    
    (future
      (loop []
        (spit "my-file.txt" "HELLO\n" :append true)
        (spit "my-file.txt" "BYE\n" :append true)
        (Thread/sleep 1)
        (recur)))
    
    (def tail (p/process
               (p/tokenize "tail -f my-file.txt")
               ;; send stderr to stderr of bb, leave out stream unmodified
               {:err :inherit}))
    
    (let [rdr (io/reader (:out tail))]
      (binding [*in* rdr]
        (loop []
          (when-let [l (read-line)]
            (when (re-matches #"BYE" l)
              (println (str "[log] " l)))
            (recur)))))