shakedzy
shakedzy

Reputation: 2893

Clojure: how to execute shell commands with piping?

I found (use '[clojure.java.shell :only [sh]]) for executing shell commands with clojure. Now, while (sh "ls" "-a") does the job, (sh "ls" "-a" "| grep" "Doc") doesn't. What's the trick?

Upvotes: 13

Views: 5649

Answers (1)

Piotrek Bzdyl
Piotrek Bzdyl

Reputation: 13175

clojure.java.shell/sh executes a command (the first argument passed to sh function) with specified arguments (the rest of the parameters passed to sh).

When you execute:

(sh "ls" "-a" "| grep" "Doc")

you ask to execute ls with parameters -a, | grep and Doc.

When you type ls -a | grep Doc in your terminal then the shell interprets it as executing ls, taking its std out and pass it as std in to another process (grep) that should be started by the shell.

You could simulate what the shell is doing by starting ls as one process, take its std output and then execute grep passing output from ls as its input.

The simpler solution would be to just ask a shell process to execute everything as if it was typed in terminal:

(sh "bash" "-c" "ls -a | grep Doc")

It's important to pass -c and ls ... as separate arguments so bash gets them as a separate parameters. You also need to have the whole command you want to execute as one string (ls -a | grep Doc). Otherwise only the first argument after -c will be treated as a command. For example this won't do what you would like:

(sh "bash" "-c" "ls -a" "|" "grep Doc")

Upvotes: 26

Related Questions