diff --git a/README.md b/README.md index a882cb1..214171e 100644 --- a/README.md +++ b/README.md @@ -187,13 +187,16 @@ user=> (->> (with-out-str (check (process {:out *out*} "ls"))) str/split-lines ( ("API.md" "CHANGELOG.md") ``` -The `:out` option also supports `:string`. You will need to `deref` the process -in order for the string to be there, since the output can't be finalized if the -process hasn't finished running: +The `:out` option also supports `:string` for collecting stdout into a string +and `:bytes` for getting the raw output as a byte array. You will need to +`deref` the process in order for the string or byte array to be there, since the +output can't be finalized if the process hasn't finished running: ``` clojure user=> (-> @(process {:out :string} "ls") :out str/split-lines first) "API.md" +user=> (-> @(process {:out :bytes} "head -c 10 /dev/urandom") :out seq) +(119 -43 -68 -64 -16 -56 32 45 86 56) ``` ## Piping output diff --git a/script/wd.clj b/script/wd.clj index 8c1cf6c..370b1b0 100644 --- a/script/wd.clj +++ b/script/wd.clj @@ -8,6 +8,7 @@ ;; :err - dump to stderr ;; :ls - dir of to stdout ;; :env - dump env to stdout +;; :echo - redirect the content of stdin to stdout ;; :grep - returns all lines from stdin matching ;; :upper - read and emit lines from stdin, but converted to uppercase ;; :ps-me - dump some info for current process (macOS & Linux only) @@ -21,6 +22,7 @@ ":err" (binding [*out* *err*] (println val)) ":ls" (pr (->> val io/file (.listFiles) (map str) sort)) ":env" (pr (->> (System/getenv) (into {}))) + ":echo" (io/copy System/in System/out) ":grep" (doseq [l (->> *in* io/reader line-seq (filter #(str/includes? % val)))] (println l)) ":upper" (doseq [l (->> *in* io/reader line-seq)] diff --git a/src/babashka/process.cljc b/src/babashka/process.cljc index 20a30f4..d4000d4 100644 --- a/src/babashka/process.cljc +++ b/src/babashka/process.cljc @@ -328,7 +328,9 @@ (defn- copy [in out encoding] (let [[out post-fn] (if (keyword? out) (case out - :string [(java.io.StringWriter.) str]) + :string [(java.io.StringWriter.) str] + :bytes [(java.io.ByteArrayOutputStream.) + #(.toByteArray ^java.io.ByteArrayOutputStream %)]) [out identity])] (io/copy in out :encoding encoding) (post-fn out))) @@ -366,10 +368,12 @@ stdout (.getInputStream proc) stderr (.getErrorStream proc) out (if (and out (or (identical? :string out) + (identical? :bytes out) (not (keyword? out)))) (future (copy stdout out out-enc)) stdout) err (if (and err (or (identical? :string err) + (identical? :bytes err) (not (keyword? err)))) (future (copy stderr err err-enc)) stderr)] @@ -425,8 +429,8 @@ For redirecting to Clojure's `*in*`, `*out*` or `*err*` stream, set the corresponding option accordingly. The `:out` and `:err` options support `:string` for writing to a string - output. You will need to `deref` the process before accessing the string - via the process's `:out`. + output and `:bytes` for writing to a byte array. You will need to `deref` + the process before accessing the string or byte array via the process's `:out`. To redirect `:err` to `:out`, specify `:err :out`. For writing output to a file, you can set `:out` and `:err` to a `java.io.File` object, or a keyword: - `:write` + an additional `:out-file`/`:err-file` + file to write to the file. diff --git a/test/babashka/process_test.cljc b/test/babashka/process_test.cljc index 66bd644..e522cb2 100644 --- a/test/babashka/process_test.cljc +++ b/test/babashka/process_test.cljc @@ -488,3 +488,13 @@ (.close in) @res (is (false? (p/alive? res)))))) + +(deftest byte-array-out-test + (when-let [bb (u/find-bb)] + (let [ba (byte-array (range 1000)) + result (-> (format "%s %s :echo" bb u/wd) + (process {:in ba :out :bytes}) + deref + :out)] + (is (bytes? result)) + (is (= (seq ba) (seq result))))))